Nest.js生产环境CORS/未授权问题:前端部分API无法调用
问题排查与修复方案
核心原因
浏览器报错提示“预检请求的响应不符合要求(不允许重定向)”是关键:
- Postman不受浏览器CORS策略约束,所以所有接口都能正常调用;
- 本地环境没有触发重定向逻辑(比如无HTTPS强制跳转、代理配置不同),所以接口正常;
- 生产环境中,
/stock接口的OPTIONS预检请求被服务器重定向,而浏览器禁止预检请求被重定向,直接拦截了后续请求; - 部分可用接口应该是简单请求(如GET/POST,无自定义请求头、Content-Type为
application/x-www-form-urlencoded),这类请求不会触发OPTIONS预检,所以能绕过拦截。
排查步骤
- 检查生产服务器的重定向规则:比如Nginx/Apache是否有强制HTTPS跳转、路径重写等逻辑,确认OPTIONS请求是否被包含在重定向范围内。
- 确认CORS中间件的执行顺序:
app.use(cors())必须放在所有路由、重定向中间件、解析中间件(如express.json())之前,否则预检请求还没经过CORS处理就被重定向了。 - 对比可用/不可用接口的请求类型:查看不可用接口是否使用了PUT/DELETE方法、自定义请求头或非标准Content-Type,这些都会触发预检请求。
修复方案
1. 调整服务器重定向规则,排除OPTIONS请求
以Nginx为例,在HTTPS跳转配置中添加排除规则:
server { listen 80; # 排除OPTIONS请求,直接返回204 if ($request_method = OPTIONS) { return 204; } # 其他HTTPS跳转逻辑 return 301 https://$host$request_uri; }
2. 修正CORS中间件的执行顺序
确保CORS处理逻辑优先执行,示例代码:
const express = require('express'); const cors = require('cors'); const app = express(); // 先配置CORS,放在最前面 app.use(cors({ origin: 'http://localhost:3000', // 生产环境替换为实际前端域名 credentials: true, // 如果需要携带Cookie,必须开启 optionsSuccessStatus: 200 })); // 再加载其他中间件和路由 app.use(express.json()); app.use('/api', require('./routes')); app.listen(3001);
3. 验证预检请求响应
在浏览器网络面板中查看OPTIONS请求的响应:
- 状态码应为200或204;
- 响应头需包含
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers(如果有自定义头)。
内容的提问来源于stack exchange,提问作者brook_t
相关产品推荐
相关产品推荐

