Nginx请求头正确转发需四点:必须配置四项proxy_set_header保留关键头;CORS头须加always参数否则OPTIONS响应缺失;禁用if+proxy_pass混用,改用两个有序location分离预检与转发;大header场景需调优client_header_buffer_size和large_client_header_buffers。

Linux 下 Nginx 实现请求头正确转发,关键不在“转发动作”本身,而在于 header 的保留、透传与安全控制。很多 502、400、跨域失败或后端收不到 Host/X-Real-IP,其实都源于 header 处理配置不完整或逻辑冲突。
必须设置的 proxy_set_header 四项基础头
仅写 proxy_pass 不够,后端常因缺失关键头而拒绝服务或识别错误。以下四行应作为每个反向代理 location 的标配:
- proxy_set_header Host $host; —— 保证后端看到原始请求域名,而非 upstream 地址
- proxy_set_header X-Real-IP $remote_addr; —— 提供客户端真实 IP(非 Nginx 本机 IP)
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; —— 支持多层代理链,自动追加 IP 链
- proxy_set_header X-Forwarded-Proto $scheme; —— 让后端知道用户用的是 HTTP 还是 HTTPS,避免混合内容或重定向死循环
跨域 OPTIONS 预检必须加 always 参数
浏览器对带认证或自定义头的请求(如含 Authorization、Content-Type: application/json),会先发一次 OPTIONS 请求。若只写:
add_header 'Access-Control-Allow-Origin' '*';该头不会出现在 OPTIONS 响应中——因为 Nginx 默认只在 2xx/3xx 响应里注入 add_header,而 return 204; 是无 body 的成功响应,不触发默认注入。
正确写法是所有 CORS 头都显式加 always:
- add_header 'Access-Control-Allow-Origin' '*' always;
- add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
- add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
- add_header 'Access-Control-Max-Age' 1728000 always;
验证方式:curl -I -X OPTIONS http://your-domain/api/v1/test,确认响应头中包含全部上述字段。
避免 if + proxy_pass 混用导致 header 丢失
常见错误是在同一 location 中用 if 判断 OPTIONS 并 return,同时又写 proxy_pass:
if ($request_method = 'OPTIONS') {
add_header ... always;
return 204;
}
proxy_pass http://backend;
}
这种写法违反 Nginx 上下文规则:if 块内 proxy_pass 行为不可靠,部分版本会丢弃 proxy_set_header,造成后端收不到 Host 或 X-Real-IP,直接返回 502。
推荐拆成两个独立 location,按顺序定义:
- 先定义专用于预检的 location(匹配更精确,优先级更高):
location ~ ^/api/.*$ {<br> if ($request_method = 'OPTIONS') {<br> add_header ... always;<br> return 204;<br> }<br>} - 再定义实际转发的 location:
location /api/ {<br> proxy_pass http://backend;<br> proxy_set_header ...;<br>}
Nginx 按配置顺序匹配,确保 OPTIONS 被第一个 location 拦截,不会落到 proxy_pass 块中。
大 header 场景需调优 client_header_buffer_size
上传 JWT Token、长 Cookie 或嵌套 X-Forwarded-For 时,容易触发 400 Bad Request 或静默断连,日志显示 client sent too large request。这不是 body 太大(client_max_body_size 无效),而是 header 解析阶段就失败了。
关键参数要协同配置:
- client_header_buffer_size 2k; —— 单个请求初始 header 缓冲,默认 1k,建议设为 2k~4k
- large_client_header_buffers 8 16k; —— 最多分配 8 个缓冲区,每个最大 16KB;注意:单个 header 必须能放进一个 buffer,不能拼接,所以真正上限是 16KB
若业务明确使用超长 token(如 12KB JWT),可设为 large_client_header_buffers 4 32k,但避免盲目设成 16 64k——内存开销剧增且易被攻击耗尽。


















