反向代理中请求头设置
location /superone/ {
proxy_pass http://1xx.xx.xx.xx:1x13/;
proxy_redirect default;
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;
}
然后就可以在反向代理的服务器程序中获取到真实的请求ip
if request.headers.get('X-Real-IP'):
ip_address = request.headers.get('X-Real-IP')
elif request.headers.get('X-Forwarded-For'):
ip_address = request.headers.get('X-Forwarded-For').split(',')[0]
else:
ip_address = request.remote_addr
你的 Nginx 配置缺少了针对“流式传输”的关键配置,导致了这个问题。
根本原因分析:
Nginx 默认开启缓冲 (Buffering):
你的 Python 后端是使用 yield 一点一点往外吐数据的(流式传输)。
但是 Nginx 默认会把后端吐出来的数据全部存到内存里,等后端彻底运行完了,再一次性发给浏览器。
结果:Python 以为发给 Nginx 了,但浏览器那边一直收不到数据(因为被 Nginx 扣住了)。等到超时了,Nginx 就会切断连接,或者因为缓冲区满了处理不当报错 403/502。
缺少超时设置:
批量下载通常耗时较长,Nginx 默认 60秒 就会切断连接。
✅ 修正后的 Nginx 配置
location /superone/ {
# 注意:末尾的斜杠 / 很重要,它会把 /superone/ 去掉,
# 即请求 /superone/api/xxx 会变成后端的 /api/xxx
proxy_pass http://xx.xx.xx.xx:1x13/;
# --- 核心修复:关闭缓冲 ---# 告诉 Nginx 收到一点数据就立马发给前端,不要存着proxy_buffering off;proxy_cache off;# 开启分块传输支持chunked_transfer_encoding on;# --- 核心修复:增加超时时间 ---# 防止下载大文件时 Nginx 认为服务器卡死而切断连接proxy_read_timeout 600s;proxy_send_timeout 600s;# --- 其他优化 ---# 允许上传大文件(配合你的前端限制)client_max_body_size 20M;# 标准 Header 配置proxy_redirect default;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;# 禁用 keepalive,防止流式连接被复用导致混乱proxy_http_version 1.1;proxy_set_header Connection "";}
如果外国服务器反向代理到国内服务器,但没备案,可能会直接就被拦截然后403,提示ICP备案。
经过是这样的:
你的浏览器访问境外服务器 A (xxx.com)。
服务器 A 的 Nginx 收到请求,准备转发给国内阿里云服务器 B (xx.xx.xx.xx)。
关键点:你的 Nginx 配置里写了 proxy_set_header Host $host;。这意味着,A 服务器在转发时,告诉了 B 服务器:“我是来访问 xxx.com 的”。
阿里云的防火墙检测到了 HTTP 请求头里的 Host: xxx.com。
阿里云一查数据库:“这个域名没有在我这里进行 ICP 备案”。
拦截! 阿里云直接劫持了 HTTP 连接,返回了这个“未备案拦截页面”给你,而不是把请求交给你的 Python 后端。
前端收到的不是 JSON,而是这个 HTML,解析失败或状态码不对,导致报错。
怎么解决?(最快的方法)
你不需要去备案(如果你只是把国内机器当后端计算节点的话)。
你只需要欺骗阿里云,不要告诉它你访问的是 xxx.com,而是直接访问 IP。
请修改境外服务器 A 的 Nginx 配置,修改 /superone/ 这一块:
找到这一行:
code
Nginx
proxy_set_header Host $host; # <--- 这是罪魁祸首
修改为:
code
Nginx
修改为 $proxy_host,这样转发过去的 Host 头就是 "1xx.7xx.xx.1x:10013"
阿里云看到是访问 IP 而不是域名,通常就会放行(除非它封禁了 IP 直连 HTTP)
proxy_set_header Host $proxy_host;
(通常情况下,修改 proxy_set_header Host $proxy_host; 就能解决这个问题!)