nginx关于add_header的坑

一 场景1 

nginx关于add_header的坑_第1张图片

nginxA作为反向代理,nginxB作为web服务。

其中 nginxA 的日志格式需要打印上游返回的Server头: xes-app : $http_upstream_server

另外A的location配置如下:

    location /servertag  {
           default_type text/plain;
            proxy_pass http://servertag;
            proxy_set_header Host $host;
      #    proxy_pass_header Server;      # 忽略上游返回的Server的header头
            add_header Xes-App $upstream_http_server;   #向返回给用户的响应中添加Xes-App的header头

      header_filter_by_lua_block {
           local cjson =  require 'cjson'
           local h, err = ngx.resp.get_headers()   --查看响应的header信息  

           ngx.log(ngx.ERR,'-----------',cjson.encode(h))
        }

    }
 

测试1:

nginxB配置:

location /servertag {
          add_header Server 'zzt-Server';    #在返回给A的响应中添加Server的header头
          return 200 "this is a test";     
      }

 

当在B的location中加上了一个Server之后,发现B给A发送响应时,会返回两个header头!!!

一个是nginx默认会返回的Server: openresty/1.13.6.1,一个是location中添加的Server: zzt-Server,

当A没有配置 proxy_pass_header Server时,表示nginx A默认忽略B传来的Server头。因此通过ngx.resp.get_headers() 返回的table中没有包含Server字段。

但是用户收到的响应确是:

nginx关于add_header的坑_第2张图片

1 : nginx返回响应时,自动在http报文里加上了当前自己的Server标识。

2 : add_header  $upstream_http_server这个指令生效了,即虽然nginx A忽略了Server,但是$upstream_http_server这个变量还是有值的,只是在ngx.get.rep_headers()获取不到Server了。

 

当A配置了 proxy_pass_header Server时;  表示不对Server的header头忽略。

此时debug日志为:

可见,1 ngx.get.rep_headers()可以获取到Server了,而且header头是将这两个字段作为数组存储的。

2 add_header时,只会取数组中的第一个元素,也就是B 在nginx中额外加的那个Server:zzt-Server并不能返回给用户,也不能记录在日志中。也就是nginx取$upstream_http_server取的是数组中的第一个元素。

二 场景2

后端B换成Tenginx,并且在nginx.conf中加上Server-tag: zzt-Server

则 B返回给A的响应头中,那个默认的Server头已经由openresty/1.13.6.1换成了 zzt-Server,则A再记录日志,返回给用户都是zzt-Server

三  场景3

后端B是golang服务,golang代码里加上Server头,则同样可以满足场景2 的效果。

 

总结: 1  nginx在发送响应给客户端时,会加上一个默认的Server的header头,哪怕他本身在 location中通过add_header加上了Server,add_header的机制就是在尾部附加,而不是覆盖。

2 $upstream_http_xxx的形式取上游返回的header头时,如果上游同时返回了多个一样字段的header头,这个变量默认取第一个。

 

 

 

你可能感兴趣的:(nginx)