1. 程式人生 > 其它 >nginx 不轉發 header 問題

nginx 不轉發 header 問題

之前在一臺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