diff --git a/api/.env.example b/api/.env.example index 4bf037c..58882a3 100644 --- a/api/.env.example +++ b/api/.env.example @@ -4,3 +4,6 @@ POSTGRES_HOST=localhost POSTGRES_DB=postgres POSTGRES_PASSWORD=postgres POSTGRES_PORT=5432 +DATABASE_URL=postgres://user:password@localhost:5432/dbname +PORT=3000 +ALLOWED_ORIGINS=https://example.com,https://api.example.com diff --git a/api/README.md b/api/README.md index 5e44119..90a49ae 100644 --- a/api/README.md +++ b/api/README.md @@ -11,14 +11,20 @@ The server will start at http://localhost:3000 ## API Documentation -OpenAPI documentation is available at: http://localhost:3000/api/docs -Swagger UI is available at: http://localhost:3000/swagger +OpenAPI documentation is available at: + http://localhost:3000/api/docs + https://cowllector.beefy.com/api/docs +Swagger UI is available at: + http://localhost:3000/swagger + https://cowllector.beefy.com/swagger + ## Test URLs for Last Harvest Reports Endpoint ``` # Get all last harvest reports http://localhost:3000/api/v1/last-harvest-reports +https://cowllector.beefy.com/api/v1/last-harvest-reports ``` You can test this URL in your browser or using tools like curl or Postman. The API will return a JSON response with an array containing the last harvest report for each vault. diff --git a/api/src/index.ts b/api/src/index.ts index f48114c..d499db0 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -2,6 +2,7 @@ import { swaggerUI } from '@hono/swagger-ui'; import { OpenAPIHono } from '@hono/zod-openapi'; import type { Context, Next } from 'hono'; import { rateLimiter } from 'hono-rate-limiter'; +import { cors } from 'hono/cors'; import { db } from './lib/db.js'; import { lastHarvestReportApi } from './routes/last-harvest-reports'; import type { Variables } from './types'; @@ -9,6 +10,34 @@ import type { Variables } from './types'; // Initialize OpenAPIHono with the custom context type const app = new OpenAPIHono<{ Variables: Variables }>(); +// Configure CORS +const getAllowedOrigins = () => { + const origins = ['http://localhost']; + const envOrigins = process.env.ALLOWED_ORIGINS?.split(',') || []; + return [...origins, ...envOrigins]; +}; + +// Add CORS middleware before other middleware +app.use( + '*', + cors({ + origin: (origin, c) => { + const allowedOrigins = getAllowedOrigins(); + // If no origin provided or origin is in allowed list, allow it + if (!origin || allowedOrigins.includes(origin)) { + return origin; + } + // Otherwise, return the first allowed origin as fallback + return allowedOrigins[0]; + }, + credentials: true, // Allow credentials + exposeHeaders: ['Content-Length', 'X-Content-Type-Options'], + maxAge: 600, // 10 minutes + allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + allowHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'], + }) +); + // Add rate limiting middleware app.use( '*',