$http_host

$http_host

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

我有一个重写规则,但我不确定应该使用哪一个:

location = /vb/showthread.php {
    # /vb/showthread.php?50271-What-s-happening&p=846039
    if ($arg_p) {
        return 301 $scheme://$host/forum/index.php?posts/$arg_p/;
        }

我正在寻找一个答案,它不仅说“在重写规则中使用___变量”,而且还解释它们之间的理论差异。

答案1

您几乎总是应该使用$host,因为它是唯一一个无论用户代理如何行为都能保证具有合理内容的变量,除非您特别需要其他变量之一的语义。

差异解释如下nginx 文档

  • $host包含“按以下优先顺序:来自请求行的主机名,或来自‘Host’请求标头字段的主机名,或与请求匹配的服务器名称”
  • $http_host包含 HTTP“Host”标头字段的内容(如果请求中存在)
  • $server_name包含server_name处理请求的虚拟主机的 ,因为它是在 nginx 配置中定义的。如果server包含多个server_name,则只有第一个会出现在此变量中。

由于用户代理在请求行中而不是在 Host: 标头中发送主机名是合法的,尽管除了连接到代理时外很少这样做,但您必须考虑到这一点。

您还必须考虑用户代理根本不发送主机名的情况,例如古老的 HTTP/1.0 请求和现代编写糟糕的软件。如果您为多个网站提供服务,或者如果您的服务器上只有一个网站,您可以通过单个虚拟主机处理所有内容,您可以将它们转移到不提供任何服务的万能虚拟主机。在后一种情况下,您也必须考虑到这一点。

只有$host变量解释了用户代理在形成 HTTP 请求时可能做的所有事情。

答案2

我想补充一个在接受的答案中没有提到的另一个重要点。

$host不是有端口号,而$http_host确实包含端口号。

编辑: 不总是。

我设置了一个标题“add_header Y-blog-http_host“$http_host”always;”

然后curl -I -L domain.com:80(或 443)并且标头根本不显示端口号。已使用 nginx-extra 1.10.3 验证。是因为它是常见的 http(s) 端口还是 nginx 配置?此评论只是说事情没有总是按你的想法行事。

答案3

TL;DR: 如果你不使用正则表达式,server_name你可以忽略这个答案

答案4

$http_host

$http_host始终等于Host请求标头字段

Host: example.org

$host

$host优先顺序如下(从高到低):

  • 请求行中的主机名
    GET http://example.org/test/ HTTP/1.1
    
  • Host请求标头字段
  • (在 Nginx 配置中)匹配请求server_name,即使server_name是通配符(例如server_name *.example.org;:)

$server_name

$server_name等于server_name(在 Nginx 配置中),即使server_name是通配符(例如server_name *.example.org;:)

请求行中的主机名

当打开 URL http://host.name/test/...

大多数浏览器都像这样发送请求

GET /test/ HTTP/1.1
Host: host.name

大多数浏览器不会发送这样的请求

GET http://host.name/test/ HTTP/1.1

参考:ngx_http_core_moduleNginx$host验证

相关内容