nginx 不轉發 header 問題
阿新 • • 發佈:2022-12-06
之前在一臺ECS上搭了個nginx搞跳轉服務,昨天突然發現header中自定義資料一直獲取不到。因為利用nginx跳轉時讀取header異常,不用nginx時讀取header正常。
先來看看nginx.conf配置檔案:
worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name http://11.239.162.48; #charset koi8-r; #access_log logs/host.access.log main; location / { #root html; #index index.html index.htm; proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://11.239.162.48:7000; client_max_body_size 100m; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
調查
檢視nginx的log日誌時,也沒有明顯的異常記錄。查了下網路上的相關資訊,有以下兩點:
1、預設的情況下nginx引用header變數時不能使用帶下劃線的變數。要解決這樣的問題只能單獨配置underscores_in_headers on;
2、預設的情況下會忽略掉帶下劃線的變數。要解決這個需要配置ignore_invalid_headers off。
檢視自己header中自定義的變數時,有一個project_id包含下劃線,介面處理時一直獲取不到其值,所以提示異常。
不過,我僅將underscores_in_headers on配置資訊加到http塊中去了,業務恢復正常。
http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; underscores_in_headers on; #keepalive_timeout 0; keepalive_timeout 65;
分析
需要看看nginx的一段原始碼,其中有這麼一個片段:
ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,ngx_uint_t allow_underscores) if (ch == '_') { if (allow_underscores) { hash = ngx_hash(0, ch); r->lowcase_header[0] = ch; i = 1; } else { r->invalid_header = 1; } break; }
即包含一個關鍵變數:allow_underscores,是否允許下劃線。
原來nginx對header name的字元做了限制,預設 underscores_in_headers 為off,表示如果header name中包含下劃線,則忽略掉。而我的自定義header中恰巧有下劃線變數。
所以,後續再碰到類似情況,要麼header中自定義變數名不要用下劃線,要麼在nginx.conf中加上underscores_in_headers on配置。
原始碼地址為:https://trac.nginx.org/nginx/browser/nginx/src/http/ngx_http_parse.c