简述
以前一直没有太关注 nginx 的 proxy_set_header 这个参数;
直到最近我的遇到一个事情, 发现配置的 header 传递不到后端服务器去了,
排查了一下, 才发现这里有几个有个巨大的陷阱。
简述结论:
- location 内要么不配置 proxy_set_header, 要么就把所有的外部 proxy_set_header 项都再配置一遍;
- 有下划线的 header 会被默认删除
限制一: proxy_set_header 的继承和默认值
一、location 内的 proxy_set_header 的继承开关
是否继承外部的 proxy_set_header 值, 在 location 里面有一个开关;
就是这个 location 内是否存在一个 proxy_set_header 定义;
如果有一个或更多, 则关闭继承; 一个都没有, 则继承开启
二、proxy_set_header 的默认值
location 块有 2 个默认的 proxy_set_header 配置, 即
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
$proxy_host 就是 proxy_pass 所指向的地址(域名或ip地址);
Connection 的目的是主动关闭与后端的连接;
无论内部是否有 proxy_set_header, 这2个值都是有的; 除非:
- 内部把这2个值给修改了
- 外部有定义 且继承有效时 继承了过来;
举几个例子
|
|
v0 接口因为内部没有 proxy_set_header,所以使用的 继承+默认值;
且继承来的值没有覆盖 2 项默认值; 所以到上游时有 4 个 header;
|
|
v1 接口因为内部没有 proxy_set_header,所以使用的 继承+默认值;
但因为继承来的外部 Host 覆盖了内部的 1 个默认值;
所以内部只有一个默认值 Connection: close 会有效;
此时发给上游的请求中, header 如下
|
|
v2 接口因为内部有 一个 proxy_set_header,所以继承被关闭了;
于是只有 2 个默认值 + 自定义的一项 xff, 于是到上游只有 3 个 header 值;
|
|
v3 接口内有多个 proxy_set_header 所以继承是关闭的; 且通过内部定义覆盖了 2项默认值;
此时发给上游的请求中, header 如下
注意这里因为 Connection 是空值, 默认会被删除, 所以只有 3 项
|
|
所以结论是, 要么 location 内不要配置 proxy_set_header, 要么就把所有的项目都配置一遍;
说明: 这里并没有考虑其它如 User-Agent, Accept, Accept-Encoding 这些 header,
因为这些都是属于客户端来时有就转发, 没有也不会影响请求转发;
限制二: 带有短横线的header项不转发
|
|
例如这种就默认不会被转发到后端去,
如果确实需要将这个带下划线的 header 转过去, 需要在 http 块进行配置
|
|
网上查询到的说法是:
丢弃的原因是为了避免在将 header 映射到 CGI 变量时混淆,因为在此过程中,破折号和下划线都映射到了下划线;
所以默认就给丢弃了。
一般情况下 转发到上游服务器时,报文头的默认变化
- 删除所有空值的报文头
- 包含下划线的报文头会被丢弃
- Host 报文头会被重写为 $proxy_host 变量值
- Connterction 报文头会被修改为 close
- http1.1 的请求会被修改为 http1.0, 如果需要 1.1 需要单独指定 proxxy_http_version 1.1;