React请求Nginx反向代理的/product服务时出现CORS重定向错误
解决React调用Nginx代理接口的CORS拦截问题
问题现象
Postman请求http://localhost/product服务正常,但React前端调用时触发CORS拦截,错误信息如下:
Access to XMLHttpRequest at 'http://localhost/product' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
用户Nginx配置如下:
worker_processes 4; events { worker_connections 1024; } http { server { listen 80; charset utf-8; location / { # auth_request /auth; proxy_pass http://user_services:8001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } location /product/ { auth_request /auth; # auth_request_set $auth_status $upstream_status; rewrite ^/product/(.*) /$1 break; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; add_header 'Access-Control-Allow-Origin' '*' always; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } proxy_pass http://onboarding_project:8002; } location /notification/ { # auth_request /auth; # auth_request_set $auth_status $upstream_status; rewrite ^/notification/(.*) /$1 break; proxy_pass http://notification_service:8006; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } location /payment/ { # auth_request /auth; rewrite ^/payment/(.*)$ /$1 break; proxy_pass http://payment_microservices:8003; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' 'http://localhost:3000'; add_header 'Access-Control-Allow-Methods' 'POST, OPTIONS'; # Adjust this based on your allowed methods add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; # Adjust the headers as needed add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } add_header 'Access-Control-Allow-Origin' 'http://localhost:3000' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always; } location = /auth { internal; proxy_pass http://user_services:8001/api/user/auth; add_header 'Access-Control-Allow-Origin' 'http://localhost:3000' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always; } } }
React客户端请求代码:
const response = await axios.get("http://localhost/product", { headers: { Authorization: "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2OTU2NzYzODEsImV4cCI6MTY5NTY3OTk4MSwiYXVkIjoiNjUxMWY2YWRkN2Q4YmMyZDIyYTE0MWY2IiwiaXNzIjoiaW50ZWxsaWJsb2NrLmNvbSJ9.bJ5Qd6d9GvGnqJu5UFT8m4UTvZsEmly13QqVbMBwFz0" } }); console.log(response, "okayyy"); } catch (e) { console.log(e); }
问题根源
- 路径重定向问题:React请求的是
http://localhost/product(不带末尾斜杠),而Nginx配置的location是/product/(带斜杠),Nginx会自动重定向到带斜杠的路径,但浏览器的CORS预请求(OPTIONS)不允许重定向,直接触发拦截。 - CORS头不兼容:请求携带
Authorization头,此时Access-Control-Allow-Origin不能设为*,必须指定具体源(如http://localhost:3000),否则浏览器会拒绝响应。 - OPTIONS请求未跳过auth校验:预请求不需要执行
auth_request校验,否则/auth接口的响应可能干扰CORS处理。
解决方案
1. 修改location匹配规则,避免重定向
将location /product/改为location ^~ /product,该规则会匹配所有以/product开头的请求(无论是否带末尾斜杠),避免Nginx自动重定向。
2. 调整OPTIONS请求逻辑,跳过auth校验
在/product的location中,先判断请求方法为OPTIONS时,直接返回CORS头并结束请求,不执行auth_request和后续代理逻辑。
3. 统一CORS头配置
将/product的CORS头与payment模块对齐,指定具体Origin,确保携带Authorization头时的兼容性。
修改后的/product配置片段
location ^~ /product { # 对OPTIONS请求直接返回CORS头,跳过auth和代理 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' 'http://localhost:3000' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } # 非OPTIONS请求执行auth校验 auth_request /auth; rewrite ^/product/(.*) /$1 break; rewrite ^/product$ / break; # 处理不带斜杠的根路径请求 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; # 非OPTIONS请求返回CORS头 add_header 'Access-Control-Allow-Origin' 'http://localhost:3000' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range' always; proxy_pass http://onboarding_project:8002; }
验证步骤
- 保存修改后的Nginx配置,执行
nginx -s reload重启服务。 - 重新发起React客户端请求,检查是否仍有CORS错误。
内容的提问来源于stack exchange,提问作者Balajee Mishra
相关产品推荐
相关产品推荐

