轉載自:https://www.jianshu.com/p/fd16b3d10752
如果沒有特別注意 proxy_set_header 配置,使用 proxy_set_header 可能會引起以下問題:
- 丟失需要的 header 信息
- 拿到意外的 Host 信息
- upstream 中的 keepalive 不能生效
在server{}字段,要么,設置齊全關於常用的proxy_set_header, 要么,
要么就在server{}字段一個都不設置,但是在server{}字段的上級要設置齊全。
有點繞,
如果在server{}字段設置了任何的proxy_set_header, 那么上級的proxy_set_header都不會繼承,只使用server{}字段上默認和新設置的的而已
server{}字段,系統有兩個默認
分別是
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
官方文檔
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header
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; 允許重新定義或附加字段到傳遞給代理服務器的請求頭。該值可以包含文本、變量及其組合。
當且僅當當前級別上沒有定義 proxy_set_header 指令時,這些指令從上級繼承。默認情況下,只有兩個值被重新定義:
問題的關鍵
在當前級別的配置中沒有定義 proxy_set_header 指令時,這些指令從上級繼承。
如果當前級別的配置中已經定義了 proxy_set_header 指令,在上級中定義的 proxy_set_header 指令在當前級別都會失效
舉個例子:
這個配置,如果用戶訪問 example.com/test/index.html,后端服務拿到的 Host 值是 example.com_test,
而不是期望的 example.com;后端服務器會收到 Connection: close 的 Header,
而不能復用連接;后端服務器也不能從 Header 中獲取到 X-Real-IP。
http { ... proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; upstream example.com_test { server 127.0.0.1:8080; keepalive 16; } server { server_name example.com; location ^~ /test/ { proxy_set_header test test; proxy_pass http://example.com_test; } } }
注意: 在 location ^~ /test/ {...} 中真正生效的 proxy_set_header 只有這三個
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
proxy_set_header test test;
正確的配置
http { ... proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; upstream example.com_test { server 127.0.0.1:8080; keepalive 16; } server { server_name example.com; location ^~ /test/ { proxy_set_header test test; proxy_set_header Host $host; proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://example.com_test; } } }
