官网关于proxy_set_header的说明如下:
Syntax: proxy_set_header field value;
Default: proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context: http
, server
, location
Allows redefining or appending fields to the request header passed to the proxied server. The value
can contain text, variables, and their combinations. These directives are inherited from the previous level if and only if there are no proxy_set_header
directives defined on the current level. By default, only two fields are redefined:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
If caching is enabled, the header fields “If-Modified-Since”, “If-Unmodified-Since”, “If-None-Match”, “If-Match”, “Range”, and “If-Range” from the original request are not passed to the proxied server.
An unchanged “Host” request header field can be passed like this:
proxy_set_header Host $http_host;
However, if this field is not present in a client request header then nothing will be passed. In such a case it is better to use the $host
variable – its value equals the server name in the “Host” request header field or the primary server name if this field is not present:
proxy_set_header Host $host;
In addition, the server name can be passed together with the port of the proxied server:
proxy_set_header Host $host:$proxy_port;
f the value of a header field is an empty string then this field will not be passed to a proxied server:
proxy_set_header Accept-Encoding "";
几个需要注意的地方:
- $host、$proxy_host和$http_host区别
- Http协议header头中的host对Nginx的影响
$host、$proxy_host和$http_host区别
为了更方便的说明这三者之间的区别,我们使用一个转发范例进行说明:
upstream myapp1 {
server app.example.com;
}
server {
listen 80;
server_name proxy1.test.com;
location / {
proxy_pass http://myapp1;
proxy_set_header Host $host;
}
}
server {
listen 80;
server_name proxy2.test.com;
location / {
proxy_pass http://myapp1;
proxy_set_header Host $proxy_host;
}
}
server {
listen 80;
server_name proxy3.test.com;
location / {
proxy_pass http://myapp1;
proxy_set_header Host $http_host;
}
}
- $host 按照如下优先级获得
- 请求行中的host
- 请求头中的Host头部
- 与一条请求匹配的server name
- $proxy_host 默认值,即代理的和转发的host
- $http_host 请求头中读取到的Host
范例1:
curl -X GET \
http://proxy1.test.com/ \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Host: proxy1.test.com' \
-H 'Referer: http://proxy1.test.com/' \
-H 'cache-control: no-cache'
此时$host的值为proxy1.test.com
范例2:
curl -X GET \
http://proxy2.test.com/ \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Host: proxy2.test.com' \
-H 'Referer: http://proxy1.test.com/' \
-H 'cache-control: no-cache'
此时$proxy_host的值为app.example.com
范例2:
curl -X GET \
http://proxy3.test.com/ \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Host: proxy3.test.com' \
-H 'Referer: http://proxy1.test.com/' \
-H 'cache-control: no-cache'
此时$http_host的值为proxy3.test.com
Nginx在做代理服务时,通常会启用多个server,请求会根据server name,进入相应的server配置执行流程,而Host就是Nginx进入不同server执行流程的依据,因此,在多server name的配置中,Host的正确至关重要,也要求我们在构建Http请求时,一定规范的使用Host这个header头。