排查跨域配置错误需重点检查Nginx error_log,因其记录OPTIONS被拒、405不支持、上游连接失败、add_header因状态码未生效等关键线索,而这些在access_log中不可见;应结合debug日志增强、curl模拟预检及配置语法验证进行精准定位。

排查跨域配置错误,不能只看浏览器控制台的 CORS 报错,Nginx 错误日志(error_log)里往往藏着关键线索:比如 OPTIONS 请求被拒、405 方法不支持、上游连接失败、或 add_header 因状态码未生效等。这些不会在 access_log 里体现,但会直接导致预检失败或响应头缺失。
重点查 error_log 中这几类报错
打开 Nginx 的 error_log(路径通常为 /var/log/nginx/error.log,级别建议设为 info 或 debug),重点关注以下关键词:
-
"http request method not allowed" → 表明 Nginx 拒绝了 OPTIONS 请求,常见于 location 块中用了
limit_except但没放开 OPTIONS; - "client sent invalid method" 或 "no resolver defined" → 可能是 DNS 解析失败导致 proxy_pass 转发中断,间接造成预检无响应;
-
"upstream prematurely closed connection" → 后端服务崩溃或超时,Nginx 返回 502/504,而这类错误响应默认不执行
add_header,CORS 头就丢失了; - "rewrite or internal redirection cycle" → if + return 或 try_files 配置不当引发循环,OPTIONS 请求卡死,浏览器最终超时或收到空响应。
让 error_log 显式记录跨域相关行为
默认 error_log 不记录请求方法和头信息,需主动增强日志粒度:
- 在
http或server块中添加:log_format debug_with_method '$remote_addr - $remote_user [$time_local] "$request_method $request_uri $server_protocol" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_origin"'; - 将该格式应用到 error_log 对应的 access_log(注意:这是 access_log,不是 error_log,但能辅助交叉验证);
- 对关键 location 开启调试日志(临时):
error_log /var/log/nginx/debug-cross.log debug;(需编译时含 --with-debug); - 用
nginx -T | grep -A5 -B5 "OPTIONS\|add_header\|if.*request_method"快速确认配置是否加载成功、语法是否有效。
结合 curl 模拟 + error_log 实时观察
不要只靠前端刷新,用命令行精准触发并盯住日志:
- 模拟预检:
curl -X OPTIONS -H "Origin: https://your-app.com" -H "Access-Control-Request-Method: POST" -I http://your-nginx-domain/api/test - 新开终端实时跟踪:
tail -f /var/log/nginx/error.log | grep -i -E "(options|405|50[24]|upstream)" - 若看到 405 错误且 error_log 有 "method not allowed",说明 Nginx 拦截了 OPTIONS;
若看到 502 且 error_log 提示 upstream 连接失败,则问题在后端,CORS 配置再全也无效。
注意 error_log 不会告诉你“头没加进去”,但会暴露原因
add_header 在 304、4xx、5xx 响应中默认不生效——这不是 bug,是 Nginx 设计机制。所以当你发现 OPTIONS 返回 204 但没 CORS 头,或 502 响应缺失 Access-Control-Allow-Origin,error_log 很可能显示的是上游异常,而非“header 未设置”。此时要检查:
• 是否加了 always 参数(如 add_header ... always;);
• 是否 upstream 返回了可缓存的 304,而 Nginx 缓存了无头响应;
• 是否 if ($request_method = 'OPTIONS') { return 204; } 写在了 add_header 之后(顺序错误会导致头不生效)。


















