Nginx中$ host和$ http_host的区别是什么

gla*_*ain 140 configuration nginx http-headers

在Nginx中,变量$host和变量之间有什么区别$http_host.

gla*_*ain 191

$hostCore模块的变量.

$主机

如果Host标头不可用,则此变量等于请求标头中的行Host或处理请求的服务器的名称.

在这种情况下,此变量可能与$ http_host具有不同的值:1)当Host输入头不存在或具有空值时,$ host等于server_name指令的值; 2)当Host的值包含端口号时,$ host不包含该端口号.自0.8.17起,$ host的值始终为小写.

$http_host也是同一模块的变量,但您不会使用该名称找到它,因为它通常定义为$http_HEADER(ref).

$ HTTP_HEADER

转换为小写并将"破折号"转换为"下划线"时HTTP请求标头HEADER的值,例如$ http_user_agent,$ http_referer ...;


总结:

  • $http_host始终等于HTTP_HOST请求标头.
  • $host等于$http_host,小写且没有端口号(如果存在),除非HTTP_HOST缺少或为空值.在这种情况下,$host等于server_name处理请求的服务器的指令的值.

  • $ host特别是**当前服务器块中定义的第一个`server_name`**.如果你有多个`server_name`s,只会出现第一个. (51认同)
  • 如果有多个`server_name`指令,`$ server_name`变量是否等于`server_name`指令的值或者选择的实际服务器名称? (5认同)
  • 真正.事实上,定义很常见:server_name example.com www.example.com; (3认同)
  • 现在链接有点404了。 (3认同)
  • @CMCDragonkai `$server_name` 始终等于使用 server_name 指令指定的第一个值。例如,对于“server_name example.com one.example.com Two.example.com;”,“$server_name”将始终为“example.com”,**无论用户指定了哪个主机**。事实上,如果您没有“default_server”,主机可能会完全不同(例如 example.org)。 (2认同)

Chr*_*ian 21

接受的答案及其评论似乎不再正确。文档(http://nginx.org/en/docs/http/ngx_http_core_module.html#var_host)说的$host

\n
\n

按此优先顺序:请求行中的主机名,或 \xe2\x80\x9cHost\xe2\x80\x9d 请求标头字段中的主机名,或与请求匹配的服务器名称

\n
\n

$http_host标头字段的值始终如此Host。如果请求行中的主机(如果指定)与Host标头字段不同,它们可能会有所不同。或者如果Host未设置标题。

\n

server_name仅匹配Host标头字段(http://nginx.org/en/docs/http/request_processing.html),因此$host可能与匹配的server_name.

\n


Ste*_*ing 16

$http_host

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

Host: example.org
Run Code Online (Sandbox Code Playgroud)

$host

$host按照以下优先顺序(从高到低):

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

请求行中的主机名

当打开网址http://example.org/test/...

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

GET /test/ HTTP/1.1
Host: example.org
Run Code Online (Sandbox Code Playgroud)

大多数浏览器不会像这样发送请求(但这是有效的请求)

GET http://example.org/test/ HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

验证

Nginx 测试配置

server {
    listen       80;
    server_name  *.example.org;

    location / {
        default_type "text/plain";
        return 200 "[host] = $host";
    }
}
Run Code Online (Sandbox Code Playgroud)

当一切都存在...

$host= 请求行中的主机名

Host: example.org
Run Code Online (Sandbox Code Playgroud)

该命令将

  • 连接到127.0.0.1
  • 发送请求路径为GET http://request.example.org/test/ HTTP/1.1
  • Host标题设置为Host: host.example.org
*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET http://request.example.org/test/ HTTP/1.1
> Host: host.example.org
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.23.1
< Date: Fri, 21 Oct 2022 02:00:56 GMT
< Content-Type: text/plain
< Content-Length: 28
< Connection: keep-alive
<
* Connection #0 to host 127.0.0.1 left intact
[host] = request.example.org
Run Code Online (Sandbox Code Playgroud)

当仅Host存在标头时...

$host=Host标题

GET http://example.org/test/ HTTP/1.1
Run Code Online (Sandbox Code Playgroud)
*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /test/ HTTP/1.1
> Host: host.example.org
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.23.1
< Date: Fri, 21 Oct 2022 02:01:37 GMT
< Content-Type: text/plain
< Content-Length: 25
< Connection: keep-alive
<
* Connection #0 to host 127.0.0.1 left intact
[host] = host.example.org
Run Code Online (Sandbox Code Playgroud)

当不存在时...

$host= server_name(在 Nginx 配置中)

GET /test/ HTTP/1.1
Host: example.org
Run Code Online (Sandbox Code Playgroud)
*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /test/ HTTP/1.0
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.23.1
< Date: Fri, 21 Oct 2022 02:02:20 GMT
< Content-Type: text/plain
< Content-Length: 22
< Connection: close
<
* Closing connection 0
[host] = *.example.org
Run Code Online (Sandbox Code Playgroud)

参考:ngx_http_core_moduleNginx$host验证

  • 很好的答案。问题是,“请求行中的主机名”具有最高优先级,即使请求具有虚假的“Host”标头并且与“server_name”不匹配,也会将请求路由到“server”(虚拟主机)。这是一个问题,因为 nginx 背后的应用程序倾向于使用传递的“Host”标头。遗憾的是,如果“请求行”中存在主机名,则“server_name”不会检查“Host”标头(如果请求中存在)——这是一种罕见且大多是恶意的情况。 (2认同)