nginx需显式配置才能透传cors响应头,因fastcgi协议本身不处理跨域;默认仅保留标准头,access-control-allow-origin等自定义头会被过滤,须用add_header统一注入或fastcgi_pass_header显式透传,并正确处理options预检请求。

FastCGI 本身不直接处理跨域(CORS)或 HTTP 头转发,它只是将请求以特定协议(如 FastCGI 协议)传递给 PHP-FPM 等后端。真正影响跨域头是否丢失的,是 Nginx 的代理配置和 FastCGI 参数设置——尤其是哪些响应头被允许透传给客户端。
关键原因:Nginx 默认不透传自定义/非标准响应头
Nginx 在使用 fastcgi_pass 时,默认只保留有限的“可信”响应头(如 Content-Type、Content-Length),而像 Access-Control-Allow-Origin 这类 CORS 头属于用户自定义头,会被自动过滤掉。即使 PHP 脚本中设置了这些头,Nginx 也不会原样返回给浏览器。
解决方法是在 location 块中显式启用头透传:
- 添加
fastcgi_pass_header Access-Control-Allow-Origin; - 若还需其他 CORS 相关头,一并列出:
fastcgi_pass_header Access-Control-Allow-Methods;fastcgi_pass_header Access-Control-Allow-Headers;fastcgi_pass_header Access-Control-Expose-Headers;fastcgi_pass_header Access-Control-Allow-Credentials;
更推荐的做法:用 add_header 统一注入 CORS 头
相比依赖后端输出再透传,直接在 Nginx 层统一添加 CORS 响应头更可控、更安全,也避免因 PHP 错误或未执行 header() 导致头缺失。
示例(放在 location ~ \.php$ 或 server 块中):
-
add_header Access-Control-Allow-Origin "*" always;(always确保对 2xx/3xx/4xx/5xx 响应都生效) add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE" always;add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;- 如需支持带凭证的请求,加上:
add_header Access-Control-Allow-Credentials "true" always;
注意此时Access-Control-Allow-Origin不能为*,需指定明确域名,例如https://example.com
注意 preflight(OPTIONS)请求的正确处理
浏览器发起跨域请求前,常先发一个 OPTIONS 预检请求。PHP-FPM 通常不处理 OPTIONS,会导致 405 或空响应。应在 Nginx 中拦截并直接响应:
- 在
location ~ \.php$内添加: if ($request_method = 'OPTIONS') {<br> add_header Access-Control-Allow-Origin "*";<br> add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";<br> add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization";<br> add_header Access-Control-Max-Age 1728000;<br> add_header Content-Type 'text/plain; charset=utf-8';<br> add_header Content-Length 0;<br> return 204;<br>}
验证与调试技巧
确认头是否生效,不要只看浏览器开发者工具的「Response Headers」——部分头可能被隐藏(如被标记为 non-HTTP/2 或被过滤)。建议:
- 用 curl 检查原始响应:
curl -I -H "Origin: https://test.com" https://yoursite.com/api/test.php - 检查 Nginx error.log 是否有警告,如
fastcgi_pass_header is not allowed here(说明写在了错误上下文,比如 server 块顶层而非 location 内) - 确保没有其他配置覆盖了你的头,例如多个
add_header指令会相互覆盖(Nginx 中同名指令后出现的会覆盖前面的)











