Docker容器间发起POST请求出现CORS预检验失败该如何解决?
问题根因
你对CORS的基础逻辑理解没有问题,故障核心是OPTIONS预检请求没有走到PHP的index.php逻辑,你写在PHP里的CORS响应头根本没有被返回给浏览器。
当前你用的是Nginx + PHP-FPM的架构,默认情况下Nginx会直接响应OPTIONS请求,不会转发给PHP后端处理,所以预检请求拿到的响应里没有你配置的Access-Control-Allow-Origin头,触发CORS报错。
另外你当前的CORS配置还遗漏了Access-Control-Allow-Headers,如果请求带自定义请求头,就算OPTIONS走到PHP也会报错。
解决方案
推荐两种处理方式,二选一即可:
方案一:在Nginx层处理CORS预检(性能更优)
修改你挂载到/etc/nginx/conf.d/目录下的Nginx站点配置文件,在server块中新增OPTIONS请求处理逻辑:
server { listen 80; server_name localhost; root /var/www/html; index index.php index.html; # 新增OPTIONS预检请求处理 if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin "http://localhost:8081"; add_header Access-Control-Allow-Methods "*"; add_header Access-Control-Allow-Headers "*"; add_header Access-Control-Max-Age 86400; return 204; } # 你原来的PHP转发等其他配置保持不变 location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
配置修改后重启web容器生效。
方案二:统一在PHP层处理所有CORS逻辑
如果想把CORS配置都集中在代码侧维护,需要先修改Nginx配置,确保OPTIONS请求会被转发到PHP,然后在PHP代码中增加预检请求处理:
- 确认Nginx的PHP转发规则没有过滤OPTIONS请求,默认规则即可支持
- 修改你的
index.php代码:
<?php // 优先处理OPTIONS预检请求 if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header("Access-Control-Allow-Origin: http://localhost:8081"); header("Access-Control-Allow-Methods: *"); header("Access-Control-Allow-Headers: *"); header("Access-Control-Max-Age: 86400"); exit; } // 原有业务逻辑保持不变 // error_reporting(E_ALL); // ini_set('display_errors', '1'); header("Access-Control-Allow-Origin: http://localhost:8081"); header("Access-Control-Allow-Methods: *"); require('route.php'); $router = new Router(); echo $router->handle();
注意事项
- 不要同时在Nginx和PHP中重复配置CORS头,会导致浏览器收到重复头触发报错
- 如果后续允许的来源有变动,对应配置要同步更新
Access-Control-Allow-Origin如果要配置多个来源、同时支持Cookie传递的场景,不能直接写*,需要根据请求的Origin动态判断返回
内容的提问来源于stack exchange,提问作者MaxB
相关产品推荐
相关产品推荐

