Nginx 变量 $host、$http_host 和 $server_name 有什么区别?

区分 Nginx $host 的查找顺序、$http_host 的原始请求头与 $server_name 的配置值,并给出可直接检查的访问日志示例。

最佳实践
网络请求路由与访问控制示意

$host 是 Nginx 解析出的主机名,$http_host 是客户端发送的 Host 请求头原值,$server_name 是处理当前请求的服务器配置名称。 三者在端口、缺失值和可信来源上不同,不能互相替代。

三种变量的来源

变量 取值来源 示例
$host 按顺序取请求行中的主机名、Host 请求头中的主机名,最后回退到匹配请求的服务器名称 example.com
$http_host 客户端 Host 请求头原值;缺少该头时为空 example.com:8080
$server_name 接受请求的 server 块的配置名称,通常为其首个 server_name example.com

例如客户端访问 http://example.com:8080/ 时,$http_host 可以保留 :8080,而 $host 通常只含主机名。代理收到绝对形式的请求行时,请求行中的主机名优先于 Host 头。

正确记录三个值

先在 http 上下文定义日志格式,再在 server 中引用其名称。access_log 的第二个参数是格式名称,不能直接填写格式字符串。

http {
    log_format host_debug '$remote_addr host="$host" '
                          'http_host="$http_host" server="$server_name" '
                          'status=$status request="$request"';
    server {
        listen 8080;
        server_name example.com www.example.com;
        access_log /var/log/nginx/host-debug.log host_debug;
    }
}

把相关指令并入现有配置的对应上下文,执行 nginx -t 检查语法后,再按服务管理流程重新加载。

代理与跳转应该用哪个

  • 向上游传递解析后的主机名:可以设置 proxy_set_header Host $host;,是否需要端口取决于上游路由规则。
  • 排查客户端实际发送了什么:同时记录 $http_host 和 $host。
  • 为固定域名做 HTTPS 跳转:直接使用确定的地址,如 return 301 https://example.com$request_uri;。

请求行和请求头均来自客户端。不要未经验证就把它们拼进对外跳转地址;多域名业务应先匹配允许的域名列表。

把上述变量写入访问日志后,可通过观测云 Nginx 日志采集保留并解析为不同字段。用带显式 Host 头的一次请求核对字段值,再按请求域名和实际匹配的 server 分组检查,避免把这三种名称混为一谈。

参考资料

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台