Nginx代理导致API 500错误的排查与修复指南
问题描述
前端访问 http://localhost:9527/dev-api/Login/getStaticResource 返回 500 Internal Server Error,直接访问 http://anyu-portal.test/ 正常。
技术栈
- 前端:Vue.js + Vue CLI (devServer proxy)
- 后端:ThinkPHP 5.x + PHP 7.4
- 容器:Docker Compose (nginx, php-fpm)
- 代理:Nginx 反向代理
请求链路分析
浏览器 localhost:9527/dev-api/Login/getStaticResource
↓ Vue devServer proxy (vue.config.js)
Nginx anyu-portal-frontend.test/api/Login/getStaticResource
↓ Nginx location /api/ proxy_pass (anyu-front.conf)
Nginx anyu-portal.test/Login/getStaticResource
↓ Nginx location ~ .php$ fastcgi_pass (anyu-portal.conf)
PHP-FPM anyu-portal/Public/index.php
配置文件检查
1. Vue devServer 代理配置
vue.config.js:
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: 'http://anyu-portal-frontend.test/api',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
}VUE_APP_BASE_API = /dev-api,所以:
- 请求
/dev-api/Login/getStaticResource - 被转发到
http://anyu-portal-frontend.test/api/Login/getStaticResource
2. Nginx 前端站点配置
anyu-front.conf:
server {
listen 80;
server_name anyu-frontend.test *.anyu-frontend.test;
root "/www/anyu-portal-frontend";
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_set_header Host $http_x_forwarded_host;
proxy_pass http://anyu-portal.test/;
}
}3. Nginx 后端站点配置
anyu-portal.conf:
server {
listen 80;
server_name anyu-portal.test;
root /www/anyu-portal/Public;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
}
location ~ \.php$ {
fastcgi_pass php:9000;
include fastcgi-php.conf;
include fastcgi_params;
}
}4. Docker Compose 网络配置
docker-compose.yml:
services:
nginx:
extra_hosts:
- "openapi:127.0.0.1"
- "lvs:127.0.0.1"
- "admin:127.0.0.1"
- "portal:127.0.0.1"
# 缺少: anyu-portal.test:127.0.0.1排查过程
步骤 1:直接测试后端 API
从 nginx 容器内部直接访问后端:
docker exec nginx curl -v http://anyu-portal.test/Login/getStaticResource
结果:返回 200 OK,后端 API 本身正常。
步骤 2:测试代理链路
从 nginx 容器内部通过前端域名访问:
docker exec nginx curl -v http://anyu-portal-frontend.test/api/Login/getStaticResource
结果:返回 500 Internal Server Error。
步骤 3:检查 Host 头问题
直接访问时 curl 会发送 Host: anyu-portal.test,但通过 /api/ 代理时:
proxy_set_header Host $http_x_forwarded_host;
$http_x_forwarded_host 是客户端请求的 X-Forwarded-Host 头,通常为空。当 Host 头为空时,后端 ThinkPHP 的 getStaticResource 方法无法正确识别 SERVER_NAME,导致找不到合作伙伴配置。
步骤 4:检查域名解析
nginx 容器的 extra_hosts 中没有配置 anyu-portal.test,虽然之前已经添加了,但需要确认是否生效。
根因分析
问题有两个层面:
- Host 头为空:
proxy_set_header Host $http_x_forwarded_host;设置了一个通常为空的变量,导致转发到后端时没有正确的 Host 头。 - 域名解析:nginx 容器内部无法解析
anyu-portal.test(虽然之前已添加到extra_hosts)。
后端 ThinkPHP 的 getStaticResource 方法依赖 SERVER_NAME 获取合作伙伴配置:
public function getStaticResource() {
$server_name = SERVER_NAME; // 依赖 $_SERVER['SERVER_NAME']
$redis = new Redis();
$redis->connect(C("REDIS_HOST"), C("REDIS_PORT"));
// ...
if(!C('PARTNER')) {
$this->setPartner($redis, $server_name); // 根据 server_name 获取合作伙伴
}
// ...
}
当 Host 头为空或不正确时,SERVER_NAME 无法正确识别,导致 C('PARTNER') 为空,后续操作失败。
修复方案
修复 1:修改 Nginx 代理配置
文件:services/nginx/conf.d/anyu-front.conf
# 修改前
location /api/ {
proxy_set_header Host $http_x_forwarded_host;
proxy_pass http://anyu-portal.test/;
}
# 修改后
location /api/ {
proxy_set_header Host anyu-portal.test;
proxy_pass http://anyu-portal.test/;
}修复 2:添加域名解析
文件:docker-compose.yml
services:
nginx:
extra_hosts:
- "openapi:127.0.0.1"
- "lvs:127.0.0.1"
- "admin:127.0.0.1"
- "portal:127.0.0.1"
- "anyu-portal.test:127.0.0.1" # 新增修复 3:重载 Nginx 配置
docker exec nginx nginx -s reload
验证
docker exec nginx curl -v http://anyu-portal-frontend.test/api/Login/getStaticResource
结果:返回 200 OK,JSON 数据正常。
总结
经验教训
- Host 头很重要:反向代理时,
proxy_set_header Host必须设置正确的值,后端框架(如 ThinkPHP)依赖它来识别当前站点。 - 容器内部域名解析:Docker Compose 的
extra_hosts只对容器内部生效,宿主机的 hosts 文件不会自动同步到容器。 - 排查顺序:先测试直接访问后端,再测试完整代理链路,定位问题出在哪一层。
- 变量陷阱:
$http_x_forwarded_host是客户端请求头,不是 Nginx 内置变量,不要误以为它会自动填充。
最佳实践
location /api/ {
proxy_set_header Host $proxy_host; # 使用 proxy_pass 中指定的主机名
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://backend/;
}
使用 $proxy_host 可以自动获取 proxy_pass 中指定的主机名,比硬编码更灵活。
以上就是Nginx代理导致API 500错误的排查与修复指南的详细内容,更多关于Nginx代理导致API 500错误的资料请关注脚本之家其它相关文章!
相关文章
shell脚本定时统计Nginx下access.log的PV并发送给API保存到数据库
这篇文章主要介绍了shell脚本定时统计Nginx下access.log的PV并发送给API保存到数据库的实现方法 ,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下2018-09-09
国内一些常用PHP的CMS的Nginx服务器的伪静态规则整理
当我们从apache服务器转向Nginx服务器的时候,它们的伪静态规则就不一样了,所以你熟悉Nginx服务器的伪静态规则,自己写当然也好2011-03-03
强大的 Web 应⽤服务器OpenResty安装(Nginx仓库)
OpenResty 是⼀个强大的 Web 应⽤服务器,Web 开发⼈员可以使用 Lua 脚本语⾔调动 Nginx ⽀持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统2023-06-06


最新评论