server_name_in_redirect只能在server或location块中使用,控制301/302重定向时Location头的主机名:on时用server_name首个值,off时用请求Host头;不可置于http块因重定向需依赖具体server上下文。

在 Nginx 的 http 块中,server_name_in_redirect 并不是一个合法的配置指令 —— 它**只能出现在 server 块或 location 块中**,且作用范围仅限于当前上下文。把它写在 http 块里不会生效,Nginx 启动时通常会报错或静默忽略(取决于版本)。
server_name_in_redirect 是什么?
该指令控制 Nginx 在返回 301/302 重定向响应(如 return 301、rewrite ... redirect、或内部重定向触发的跳转)时,Location 响应头中的主机名部分如何生成:
- 设为
on(默认):使用当前server块中第一个server_name值; - 设为
off:使用客户端请求头中的Host字段值(更贴近原始请求)。
为什么不能放在 http 块?
因为重定向行为依赖于具体的虚拟主机(server)上下文:
– 每个 server 可能监听不同域名、端口或 IP;
– Location 头必须明确指向一个可访问的域名,而这个域名需与当前服务实例匹配;
– http 块是全局配置层,不绑定具体 server_name,无法确定“该填哪个域名”。
正确用法示例
✅ 推荐写在 server 块内:
server {
listen 80;
server_name example.com www.example.com;
<pre class="brush:php;toolbar:false;"># 让所有重定向都用 example.com(而非用户访问的 www.example.com)
server_name_in_redirect on;
location /old/ {
return 301 /new/;
# → Location: http://example.com/new/
}}
✅ 若希望保持用户原始 Host(比如多租户或反向代理场景):
server {
listen 80;
server_name ~^(?<domain>.+)$; # 动态匹配
<pre class="brush:php;toolbar:false;">server_name_in_redirect off;
location / {
return 302 /redirected/;
# 若请求 Host 是 user1.site.com → Location: http://user1.site.com/redirected/
# 若请求 Host 是 user2.site.com → Location: http://user2.site.com/redirected/
}
}
常见误区与替代方案
⚠️ 误以为设在 http 块可统一控制所有 server:不行,必须逐个 server 设置。
⚠️ 重定向仍出现错误域名?检查:
– 是否有多个 server 块匹配请求(优先级、listen 配置);
– server_name 是否包含通配符或正则,影响第一个名称的选取;
– 是否启用了 absolute_redirect off(它会让 Nginx 用相对路径代替完整 URL,绕过 server_name_in_redirect)。
如需统一行为,可用变量 + return 显式构造跳转地址:
return 301 $scheme://example.com$request_uri;
这种方式完全绕过 server_name_in_redirect,更可控、更直观。











