在前后端分离项目中,前端通常为 React 打包后的静态资源,后端由 Python(如 FastAPI/Flask)提供 API。生产环境通常使用 Nginx 作为统一入口:对外仅暴露 80/443 端口,静态资源由 Nginx 直接返回,/api 等路径转发至后端进程。该架构既能隐藏后端端口,又便于配置 HTTPS 与缓存。
本文主要介绍 Nginx 反向代理的核心配置思路与关键片段,便于快速接入与问题排查。
整体架构
客户端 → Nginx:80/443
├── / → 静态资源(React build 目录)
└── /api → 反向代理到 Python 后端(如 127.0.0.1:8000)
- 前端:执行
npm run build后生成build(或dist)目录,配置 Nginx 的root指向该目录。 - 后端:使用 Gunicorn/Uvicorn 监听本机端口(如 8000),仅对本机开放;Nginx 通过
proxy_pass将/api请求转发至该端口。
基础 Server 与静态资源配置
在 Nginx 的 conf.d 或 sites-available 目录下新建配置文件,添加 server 块:
server {
listen 80;
server_name your-domain.com;
# 前端静态资源目录
root /var/www/app/frontend/build;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
配置要点:
root:指向 React 打包后的目录。当请求/或/xxx时,Nginx 会优先查找对应文件,若不存在则查找目录,最后回退至index.html。此配置确保 React Router 能正确处理浏览器直接访问或刷新子路径的情况。try_files:$uri表示尝试匹配同名文件,$uri/表示尝试匹配同名目录,最后的/index.html将请求交由 SPA 框架自行处理路由。
反向代理 /api 到 Python 后端
在同一个 server 块中增加 location /api 配置:
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
配置要点:
proxy_pass:填写后端实际监听地址。若后端路由已包含/api前缀(如 FastAPI 的app = FastAPI(prefix='/api')),此处直接写http://127.0.0.1:8000即可。X-Forwarded-Proto:若 Nginx 前置了 HTTPS 终结,后端需通过该 Header 获取原始协议($scheme),以便正确生成重定向链接或处理安全策略。Host:若后端依赖 Host 进行虚拟主机路由或安全校验,需透传原始 Host。
路径处理的两种常见写法
方式一:前后端均保留 /api 前缀
- 前端请求:
axios.get('/api/users') - Nginx 配置:
location /api { proxy_pass http://127.0.0.1:8000; }(末尾无斜杠) - 转发结果:请求路径原样转发为
/api/users,后端需挂载在/api路由下。
方式二:Nginx 剥离 /api 前缀,后端使用根路径
- Nginx 配置:
location /api/ { proxy_pass http://127.0.0.1:8000/; }(location与proxy_pass末尾均有斜杠) - 转发结果:请求
/api/users会被重写为http://127.0.0.1:8000/users,后端只需处理/users等路由。
根据前后端约定选择其一即可。核心在于
proxy_pass末尾是否带斜杠,需与后端路由前缀严格对应。
超时与请求体大小限制
若接口涉及文件上传或长耗时操作,需适当调整超时时间与请求体大小限制:
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
client_max_body_size 20M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
HTTPS 配置与 HTTP 跳转
生产环境建议启用全站 HTTPS。使用 Certbot 申请证书后,可保留 80 端口仅用于跳转:
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
root /var/www/app/frontend/build;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
常见问题排查
| 现象 | 可能原因 | 处理思路 |
|---|---|---|
| 刷新子路径返回 404 | SPA 路由未正确回退 | 检查 try_files 末尾是否配置为 /index.html |
| 接口返回 502 Bad Gateway | 后端未启动或端口不匹配 | 确认 Gunicorn/Uvicorn 监听地址与 proxy_pass 一致 |
| 接口返回 404 Not Found | 路径前缀不一致 | 核对前端请求路径、proxy_pass 末尾斜杠及后端路由前缀 |
| 上传大文件失败 | 请求体超限或代理超时 | 调大 client_max_body_size 与 proxy_*_timeout 参数 |
总结
使用 Nginx 代理前后端分离项目时,静态资源通过 root 配合 try_files 指向 React 构建目录并回退至 index.html;API 请求通过 proxy_pass 转发至 Python 后端,并透传 Host、X-Real-IP、X-Forwarded-Proto 等关键 Header。配置时需特别注意 proxy_pass 末尾斜杠与后端路由前缀的对应关系,按需调整超时与请求体限制,并在生产环境中配合 HTTPS 与 80 端口跳转即可。


