From bf1f368a2479ecddc6f74ac935563e379b64e99a Mon Sep 17 00:00:00 2001 From: Michilis Date: Tue, 15 Jul 2025 21:56:55 +0000 Subject: [PATCH] fix: enhance CORS configuration for production with Nginx proxy - Add enhanced CORS headers for Swagger UI compatibility - Add OPTIONS method support for preflight requests - Add additional middleware for CORS preflight handling - Add debug endpoint /api/cors-test for CORS troubleshooting - Improve Swagger UI configuration for production deployment --- server.js | 34 +++++++++++++++++++++++++++++++--- swagger.config.js | 7 ++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index 09fdaf0..0fe2d16 100644 --- a/server.js +++ b/server.js @@ -17,21 +17,49 @@ const protocol = isProduction ? 'https' : 'http'; // Middleware app.use(express.json({ limit: '10mb' })); + +// Enhanced CORS configuration for Swagger UI app.use(cors({ origin: process.env.ALLOWED_ORIGINS ? process.env.ALLOWED_ORIGINS.split(',').map(o => o.trim()) : [`${protocol}://${apiDomain}`], - methods: ['GET', 'POST'], - allowedHeaders: ['Content-Type', 'Authorization'] + methods: ['GET', 'POST', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'Accept', 'Origin', 'X-Requested-With'], + credentials: true, + optionsSuccessStatus: 200 })); +// Additional middleware for Swagger UI preflight requests +app.use((req, res, next) => { + if (req.method === 'OPTIONS') { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Accept, Origin, X-Requested-With'); + res.status(200).end(); + return; + } + next(); +}); + +// Debug endpoint to test CORS +app.get('/api/cors-test', (req, res) => { + res.json({ + success: true, + message: 'CORS test successful', + timestamp: new Date().toISOString(), + origin: req.headers.origin, + host: req.headers.host + }); +}); + // Swagger Documentation app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs, { customCss: '.swagger-ui .topbar { display: none }', customSiteTitle: 'Cashu Redeem API Documentation', swaggerOptions: { filter: true, - showRequestHeaders: true + showRequestHeaders: true, + tryItOutEnabled: true } })); diff --git a/swagger.config.js b/swagger.config.js index 25a3732..c6718b2 100644 --- a/swagger.config.js +++ b/swagger.config.js @@ -6,6 +6,11 @@ const apiDomain = process.env.API_DOMAIN || 'localhost:3000'; const isProduction = process.env.NODE_ENV === 'production'; const protocol = isProduction ? 'https' : 'http'; +// For production behind Nginx, we need to ensure the URL doesn't include the internal port +const serverUrl = isProduction + ? `${protocol}://${apiDomain}` + : `${protocol}://${apiDomain}`; + const options = { definition: { openapi: '3.0.0', @@ -24,7 +29,7 @@ const options = { }, servers: [ { - url: `${protocol}://${apiDomain}`, + url: serverUrl, description: isProduction ? 'Production server' : 'Development server' } ],