本文會先由一個問題引入,而後再進行多種狀況進行分析。html
咱們應用程序從代碼層面收到的 Header 中的 Host 的值是 upstream
的 名稱。 咱們程序是須要獲取到實際的值。因此這裏存在一個問題。node
咱們先看看咱們的 nginx
配置。python
upstream open-hz8443{ server 10.60.6.184:8000 max_fails=1 fail_timeout=3s weight=10; } server{ server_name 192.168.80.132; listen 80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 3s; proxy_read_timeout 120s; proxy_send_timeout 120s; proxy_next_upstream error timeout invalid_header http_404 http_502 http_504 http_500; location / { proxy_pass http://open-hz8443; } location ^~ /wss/v1 { proxy_pass http://open-hz8443; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; tcp_nodelay on; } }
咱們請求 http://192.168.80.132/wss/v1
, 咱們能夠在後端(10.60.6.184:8000
)獲取到 Host 的值爲 open-hz8443
。nginx
這個是咱們作了一個 腳本,用於獲取請求的全部的數據的。 腳本具體內容在文末。web
Connection: upgrade Host: open-hz8443 # 獲取到的Host 是 open-hz8443 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 10.210.20.43 - - [04/Jan/2021 15:54:46] "GET /wss/v1 HTTP/1.0" 200 -
首先這裏有知識點:後端
咱們在 Server 配了 proxy_set_header Host $host;
, 咱們在 location 是隻配置了app
proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade;
咱們的 Host 最初我認爲是會繼承 Server 配置的 proxy_set_header Host $host;
, 可是明顯是沒有繼承的,而是直接拿的 upstream
的名稱。說明沒有繼承,那麼這裏是有一個什麼規則? 咱們往下看。tcp
查詢 Nginx
官方文檔。code
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_headerserver
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 configuration 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
纔會從上一層級繼承,當咱們設置了 proxy_set_header
,也就意味着咱們不從上面 server 的 proxy_set_header Host $host;
進行繼承。
那爲何會顯示 open-hz8443
, 是由於有一個默認值
proxy_set_header Host $proxy_host;
這個 proxy_host
,
upstream
的話,也就是上面的例子$proxy_host
就是 upstream的名稱值. proxy_pass http://10.60.6.184:8000
的話,那麼 $proxy_host
表示的就是 10.60.6.184:8000
在 location ^~ /wss/v1
下面增長配置 proxy_set_header Host $host;
。
location ^~ /wss/v1 { proxy_pass http://open-hz8443; proxy_set_header Host $host; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; tcp_nodelay on; }
proxy_set_header Host $proxy_host; proxy_set_header Connection close;
proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade;
Server 設置 proxy_set_header 其餘項 | Server 設置 proxy_set_header 默認兩項 | location 設置 proxy_set_header 默認兩項 | location 設置 proxy_set_header 其餘項 | 默認值生效 | 默認值不生效 |
---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 繼承location | |
1 | 1 | 0 | 1 | 1(不繼承Server) | |
1 | 1 | 1 | 0 | 1 繼承location | |
1 | 1 | 0 | 0 | 1 繼承server | |
1 | 0 | 1 | 0 | 1 繼承location | |
1 | 0 | 0 | 0 | 1 默認 | |
1 | 0 | 0 | 11 | 1 默認 | |
1 | 0 | 1 | 1 | 1 繼承location | |
0 | 1 | 0 | 0 | 1 繼承server | |
0 | 1 | 0 | 1 | 1 默認 | |
0 | 1 | 1 | 0 | 1 繼承location | |
0 | 1 | 1 | 1 | 1 繼承location | |
0 | 0 | 0 | 1 | 1 默認 | |
0 | 0 | 1 | 0 | 1 繼承location | |
0 | 0 | 1 | 1 | 1 繼承location | |
0 | 0 | 0 | 0 | 1 默認 |
只要調用了 proxy_set_header,並無設置 host 和 connection ,默認重寫host、connection兩個頭。
記錄一次 Nginx 配置 proxy_pass 後 返回404問題
#!/usr/bin/env python import SimpleHTTPServer import SocketServer PORT = 8000 class GetHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def do_GET(self): print(self.headers) self.send_response(200, "") def do_POST(self): print(self.headers) content_length = self.headers.getheaders('content-length') length = int(content_length[0]) if content_length else 0 print(self.rfile.read(length)) self.send_response(200, "") Handler = GetHandler httpd = SocketServer.TCPServer(("", PORT), Handler) httpd.serve_forever()