Nginx配置Host字段出错

一、Host为空

1
2
# 虚拟主机的主域名
proxy_set_header Host $proxy_host;
1
2
3
# 请求头中'Host'的值
# 如果请求头中没有携带Host值,那传到服务器的请求也不含这个字段
proxy_set_header Host $http_host;
1
2
3
# 请求包含'Host'请求头时为'Host'字段的值
# 在请求未携带'Host'请求头时为虚拟主机的主域名
proxy_set_header Host $host;

注:使用$http_host变量时,在http1.1协议中,如果请求不带Host字段值,会报错400错误

  • 客户端必须在所有HTTP1.1请求消息中包含Host头字段
  • 如果请求的URI不包含所请求服务的主机名,则必须为Host头字段指定一个空值
  • HTTP1.1代理必须确保它转发的任何请求消息,都包含一个适当的主机头字段,用于标识代理请求的服务
  • 所有基于HTTP1.1服务器必须以400状态代码响应任何缺少主机头字段的HTTP1.1请求消息


$http_host
1
2
3
4
5
$http_host不是一个固定的变量,他其实是$http_HEADER通配后的结果
HEADER是一个通配符,通配的是请求头里的header属性

例如$http_content_type表示请求头里content-type属性的值
同理,$http_host指的就是请求头里的host属性


二、Host重复配置

1
2
3
# proxy.conf文件
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
1
2
3
include conf/proxy.conf; # proxy.conf文件中已经设置了Host字段值
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

注:两个proxy_set_header Host $host;语句,配置在同一个语句块中,不存在子语句块覆盖父语句块的情况


HTTP RFC2616

可以存在具有相同字段名的多个消息头字段在消息中,当且仅当该标头的整个字段值字段被定义为以逗号分隔的列表。通过将每个后续字段值附加到第一个,每个用逗号分隔。因此代理不得改变转发时这些字段值的顺序

1
2
3
4
Cache-Control: no-cache
Cache-Control: no-store
# 相当于
Cache-Control: no-cache, no-store

由于Host字段值不允许以逗号分隔nginx会报400状态码错误。


三、$host变量

$host变量的值按照如下优先级获得:

  1. 请求行中的host

    1
    GET www.test.info/index.php HTTP/1.1
  2. 请求头中的Host头部,除了端口号的部分

  3. 与一条请求匹配的server name