Nginx搭配React Router访问/api返回404 多容器前后端代理配置问题
解决方案
方案1:统一接口前缀(推荐,生产环境通用,维护成本低)
该方案从根源上避免React路由和后端接口路径冲突,不需要依赖请求头判断,稳定性更高:
- 前端所有接口请求统一添加
/api前缀,例如原来请求/themes修改为请求/api/themes - 修改
nginx.conf配置如下:
upstream backend { server app-server:8080; } server { listen 80; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # 代理所有/api前缀的接口请求到后端 location ^~ /api/ { # 去掉/api前缀后再转发,后端收到的路径还是原接口路径/themes,不需要修改后端代码 rewrite ^/api/(.*)$ /$1 break; proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 处理React静态资源和前端路由 location / { root /usr/share/nginx/html; index index.html index.htm; # 移除原配置末尾的=404,所有非静态资源请求统一返回index.html,交给React路由处理 try_files $uri $uri/ /index.html; } error_page 401 403 404 index.html; location /public { root /usr/local/var/www; } }
- 可删除package.json中的proxy配置,该配置仅在本地开发环境生效,生产打包后不会起作用,代理逻辑完全由Nginx处理。
方案2:按请求特征区分(适配无需修改前端请求路径的场景)
如果暂时不想修改前端请求路径,可以通过判断接口请求的特征头来区分转发逻辑:
- 修改
nginx.conf配置如下:
upstream backend { server app-server:8080; } # 匹配JSON请求特征 map $http_accept $is_api_request { default 0; ~*application/json 1; } # 匹配AJAX请求特征 map $http_x_requested_with $is_ajax { default 0; XMLHttpRequest 1; } server { listen 80; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { root /usr/share/nginx/html; index index.html index.htm; # 符合接口请求特征就转发到后端 if ($is_api_request) { proxy_pass http://backend; } if ($is_ajax) { proxy_pass http://backend; } # 其他请求走React路由逻辑 try_files $uri $uri/ /index.html; } error_page 401 403 404 index.html; location /public { root /usr/local/var/www; } }
原配置问题说明
你之前的配置存在两个核心问题:
location /中同时配置了try_files和proxy_pass,且try_files末尾加了=404,静态资源匹配失败后直接返回404,不会触发React路由逻辑- 没有对页面请求和接口请求做区分,路径冲突时优先返回了后端接口内容,覆盖了React页面路由
内容的提问来源于stack exchange,提问作者Raissa Correia
相关产品推荐
相关产品推荐

