Vercel部署后Swagger UI调用Express API遇CORS请求失败问题
我用Express.js开发了一套API,配置了Swagger文档和CORS规则。这套API在Heroku上部署后运行正常,但部署到Vercel后,通过Swagger UI调用接口时一直出现以下错误:
Failed to fetch.
Possible Reasons:CORS
Network Failure
URL scheme must be "http" or "https" for CORS request.
我已经添加了vercel.json文件配置CORS响应头,但问题依然存在。相关代码配置如下:
Express中的Swagger及CORS配置
// Swagger definition const swaggerDefinition = { swagger: "2.0", info: { version: "1.0.0", title: "API", description: "API Documentation for fetching data" }, host: "localhost:3000", schemes: ["http"] }; // Options for the swagger docs const options = { swaggerDefinition, apis: ["./api/index.js"], // Update with actual path to the API file }; // Initialize swagger-jsdoc const swaggerSpec = swaggerJsdoc(options); const CSS_URL = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.1.0/swagger-ui.min.css" // Then pass these options to cors: app.use(cors(options)); // Serve swagger docs app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, { customCss: '.swagger-ui .opblock .opblock-summary-path-description-wrapper { align-items: center; display: flex; flex-wrap: wrap; gap: 0 10px; padding: 0 10px; width: 100%; }', customCssUrl: CSS_URL, }));
vercel.json配置
{ "version": 2, "builds": [ { "src": "api/*.js", "use": "@vercel/node" } ], "routes": [ { "src": "/(.*)", "dest": "/api/index.js" } ], "headers": [ { "source": "/api/index.js", "headers": [ { "key": "Access-Control-Allow-Credentials", "value": "true" }, { "key": "Access-Control-Allow-Origin", "value": "*" }, { "key": "Access-Control-Allow-Methods", "value": "GET,OPTIONS,PATCH,DELETE,POST,PUT" }, { "key": "Access-Control-Allow-Headers", "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" } ] } ] }
1. 修正Swagger配置的Host和Scheme
你的Swagger定义里硬编码了本地地址localhost:3000和http协议,但Vercel部署后是HTTPS的线上域名,这会导致Swagger UI用本地地址调用线上API,直接触发CORS和URL协议错误。
修改Swagger定义,动态适配生产环境:
const swaggerDefinition = { swagger: "2.0", info: { version: "1.0.0", title: "API", description: "API Documentation for fetching data" }, host: process.env.NODE_ENV === 'production' ? process.env.VERCEL_URL : "localhost:3000", schemes: process.env.NODE_ENV === 'production' ? ["https"] : ["http"] };
Vercel会自动注入VERCEL_URL环境变量,直接使用即可。
2. 修复CORS中间件的配置错误
你把Swagger的配置对象传给了cors()中间件,这完全错误——cors()需要的是CORS规则配置,不是Swagger的选项。
把这行代码:
app.use(cors(options));
替换为:
// 自定义符合需求的CORS规则 app.use(cors({ origin: '*', credentials: true, methods: ['GET', 'OPTIONS', 'PATCH', 'DELETE', 'POST', 'PUT'], allowedHeaders: ['X-CSRF-Token', 'X-Requested-With', 'Accept', 'Accept-Version', 'Content-Length', 'Content-MD5', 'Content-Type', 'Date', 'X-Api-Version'] }));
这样CORS规则才能正确生效。
3. 调整vercel.json的Headers匹配范围
当前source: "/api/index.js"仅匹配单个文件的请求,但Swagger UI调用的是API接口路径(比如/api/users),需要扩大匹配范围:
"headers": [ { "source": "/(.*)", "headers": [ { "key": "Access-Control-Allow-Credentials", "value": "true" }, { "key": "Access-Control-Allow-Origin", "value": "*" }, { "key": "Access-Control-Allow-Methods", "value": "GET,OPTIONS,PATCH,DELETE,POST,PUT" }, { "key": "Access-Control-Allow-Headers", "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" } ] } ]
这样所有请求都会带上正确的CORS响应头。
4. 确认Vercel环境变量设置
在Vercel项目的「环境变量」设置中,添加NODE_ENV并设为production,确保Swagger的动态配置生效。
内容的提问来源于stack exchange,提问作者Software14

