Nginx 通过 proxy_set_header Host 可重写转发给后端的 Host 请求头,常用于路由、鉴权及生成绝对 URL;常用写法包括 $host、$host:$server_port 或硬编码域名,并需配合 proxy_pass 正确配置以避免为空或错误。

Nginx 使用 proxy_set_header 可以修改转发给后端服务的请求头,其中重写 Host 头是最常见也最关键的配置之一。默认情况下,Nginx 会将客户端原始的 Host 头透传给上游(upstream),但很多时候你需要覆盖它,比如后端服务依赖特定的 Host 值来路由、鉴权或生成绝对 URL。
为什么要重写 Host 请求头
后端应用(如 Django、Spring Boot、Node.js 服务)常通过 Host 请求头判断当前访问域名,用于:
- 生成正确的跳转地址或静态资源链接(如
https://api.example.com/v1/users) - 多租户或虚拟主机场景下做路由分发
- 绕过因反向代理导致的 Host 不匹配校验(例如某些 API 网关强制校验 Host)
- 统一后端入口,避免后端直接暴露真实域名或 IP
基本语法与常用写法
在 location 或 server 块中使用:
proxy_set_header Host $host;
这是最常用的一种,把客户端请求中的 Host 值原样传给后端。但注意:$host 不带端口,$http_host 保留原始值(含端口和大小写)。更稳妥的写法是:
proxy_set_header Host $host:$server_port;
如果后端固定需要某个域名(比如内部服务只认 backend.internal),可硬编码:
proxy_set_header Host backend.internal;
配合 proxy_pass 的注意事项
当 proxy_pass 指向带域名的地址(如 http://10.0.1.20:8080)时,Nginx 默认会用该地址的 host 替换原始 Host;但如果 proxy_pass 后跟的是变量(如 $backend)或没有明确 host,则必须显式设置 Host 头,否则可能为空或出错。
典型安全写法示例:
location /api/ {
proxy_pass http://10.0.1.20:8080/;
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;
}
注意末尾的 /:它会剥离 /api/ 前缀再转发,避免路径重复。
调试与验证方法
可通过以下方式确认 Host 是否被正确改写:
- 在后端加日志打印
request.headers.get('Host')(Python Flask/FastAPI)或req.headers.host(Node.js) - 用
curl -v查看 Nginx 返回的响应头,或抓包观察发往后端的请求 - 临时用
nc -l 8080监听端口,手动发起请求查看原始 HTTP 请求头
若发现 Host 仍是原始值或为空,检查是否遗漏 proxy_set_header Host ...,或是否被其他 location 块覆盖。

















