nginx关于add_header的坑

2023-11-14

一、 add_header指令不会去重

nginx做反向代理时,如果后端返回的response中已经有该header头,则通过add_header后会返回给客户端两个同样的header头。

场景1:

 

nginxA作为反向代理,nginxB作为web服务。我是拿的openresty 1.13.6.2测试的,本质上是一样,其中A是openresty 1.15.8.1吗,B是openresty 1.13.6.2。

其中 nginxA 的日志格式里配置了打印上游返回的Server头: xes-app : $http_upstream_server

测试1:   add_header指令对重复指令的处理。

A的location配置如下:

server {
      listen 80;
      server_name test.header.com;
      access_log /home/nginx/logs/test.header.com_access.log main;
      error_log  /home/nginx/logs/error.log  debug;

      location / {
          set $upstream 'test.header.com';
          proxy_pass http://$upstream;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          
      }
}

nginxB的配置如下:

server{
      listen 80;
      server_name test.header.com;
      access_log  /home/nginx/logs/test.header.com.log main;
      index  index.php index.html index.htm;
      location / {
            add_header Server 'MytestB'; 
            return 200 "this is test header from zlear"; 
      }       
}

这种配置下,B返回给A响应时会加上一个'Server: MytestB'的header。

  • 直接访问B:

  • 访问A,A反向代理到B:

此时只有一个Server的 header,而且是A的openresty 版本标识。

测试1结果:

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

2:  单纯的配置add_header指令时,如果response中已经有该header了,则会重复添加。

3:  通过反向代理NginxA之后,A会隐藏掉B返回给自己的Server Header头,并将自己的Server标识返回给客户端。

 

测试2: proxy_hide_headerproxy_pass_header指令对add_header有影响吗?

说明:proxy_hide_header : nginx在做反向代理时,为了隐藏上游服务器的信息,不会将上游的Server返回给客户端。

语法: proxy_hide_header field;
默认值: —
上下文: http, server, location
nginx默认不会将“Date”、“Server”、“X-Pad”,和“X-Accel-...”响应头发送给客户端。proxy_hide_header指令则可以设置额外的响应头,这些响应头也不会发送给客户端。

proxy_pass_header:   和proxy_hide_header相反,如果希望允许传递某些响应头给客户端,可以使用proxy_pass_header指令。

例如: proxy_pass_header Server; 则告诉nginx服务传递上游的Server头,而不是将它自己放在响应中。

  • 在测试1的基础上,在A上加上proxy_pass_header指令:
server {
      listen 80;
      server_name test.header.com;
      access_log /home/nginx/logs/test.header.com_access.log main;
      error_log  /home/nginx/logs/error.log  debug;

      location / {
          set $upstream 'test.header.com';
          proxy_pass http://$upstream;
          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_pass_header Server;
          
      }
}

通过A访问B如下:

此时和测试1中的直接访问B结果一样。

  • 在测试1的基础上,在NginxB上添加指令add_header MytestB MytestB;
server{
      listen 80;
      server_name test.header.com;
      access_log  /home/nginx/logs/test.header.com.log main;
      index  index.php index.html index.htm;
      location / {
            add_header Server  'MytestB'; 
            add_header MytestB 'MytestB'; 
            return 200 "this is test header from zlear"; 
      }       
}

测试2结果:

1、 nginx默认会隐藏上游返回的Server 的header头,但是可以通过pass_header_header Server;来取消该限制,此时用户会收到B返回的两个header头。

2、对于其他的非默认屏蔽的header头,则NginxA会原样透传给用户。如果想屏蔽某个header头,可以通过proxy_hide_header指令。

 

二、 add_header指令会覆盖

如果在http、server、location都配置了add_header指令之后,返回给用户的是什么呢?

例如如下配置:

server {
      listen 80;
      server_name test.header.com;
      access_log /home/nginx/logs/test.header.com_access.log main;
      error_log  /home/nginx/logs/error.log  debug;
      add_header Test1 AAA;

      location / {
          set $upstream 'test.header.com';
          proxy_pass http://$upstream;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          add_header Test2 BBB;
          
      }
}

这样的配置下,会返回给用户什么header呢?

答案是只会以location的为准,在server里配置的Test1并不生效。同理在http段配置的更加不会生效。 优先级location > server > http。

 

三、 扩展

1、 ngx.resp.get_headers()

对Nginx A测试 ngx.resp.get_headers

-- header.lua

local json = require('cjson')
local h, err = ngx.resp.get_headers()
ngx.log(ngx.ERR, '-------resp header:-------', json.encode(h))

结果如下:

2020/08/06 10:07:02 [error] 5616#0: *15175 [lua] header.lua:9: -------resp header:-------{"connection":"keep-alive","content-type":"application\/octet-stream","mytestb":"MytestB","content-length":"34"} while reading response header from upstream, client: 127.0.0.1, server: test.header.com, request: "GET http://test.header.com/aaa HTTP/1.1", upstream: "http://xxxx:80/aaa", host: "test.header.com"

 

接着在A中加上配置项: proxy_pass_header Server;

再次测试结果:

2020/08/06 10:04:58 [error] 5564#0: *14655 [lua] header.lua:9: -------resp header:-------{"content-type":"application\/octet-stream","server":["openresty\/1.13.6.2","MytestB"],"connection":"keep-alive","mytestb":"MytestB","content-length":"34"} while reading response header from upstream, client: 127.0.0.1, server: test.header.com, request: "GET http://test.header.com/aaa HTTP/1.1", upstream: "http://xxx:80/aaa", host: "test.header.com"

 

结论:

1、ngx.resp.get_headers() 只能获取到proxy_hide_header外的header头,如果想获取到默认被屏蔽掉的那些header,需要用proxy_pass_header来添加。

2、 默认情况下,此api获取到的header是一个key-value形式,但是如果upstream返回了两个同样的header,lua会用数组的形式存储。

 

2、 Server-tag会覆盖Server header头

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

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

3、  代码自定义Server的header头会覆盖nginx自带的

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

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nginx关于add_header的坑 的相关文章

随机推荐

  • ES自己手动高亮

    背景 es的高亮真的是一言难尽 经常出现各种各样的高亮异常 如 高亮错位 高亮词错误等等 而且 用wildcardQuery 等 也无法高亮 可能是我技术不精吧 总是调不好这玩意 因此决定手写高亮 废话不多说 直接上代码 1 第一步 处理高
  • 方法调用:一看就懂,一问就懵?

    方法调用是不是很熟悉 那你真的了解它吗 今天就让我们来盘一下它 首先大家要明确一个概念 此处的方法调用并不是方法中的代码被执行 而是要确定被调用方法的版本 即最终会调用哪一个方法 上篇文章中我们了解到 class字节码文件中的方法的调用都只
  • CSS元素移动

    元素移动 2D平面移动 水平竖直移动 旋转 3D移动 3D旋转 立体正方体六面为图片 绕由原点指向某一定点的向量轴旋转 2D平面移动 水平竖直移动 水平竖直移动采用属性 transform中的translate x y 一起设置水平和竖直移
  • 使用 mdev 机制实现热插拔USB无线网卡 自动获取IP

    文章目录 实验环境 一 MDEV 机制 1 基本用法 2 MDEV 的配置文件 二 Kernel hotplug 三 wpa supplicant 使用方法 wpa cli 命令 四 DHCP 五 实现 1 开机脚本 2 创建 mdev 配
  • 机器人TF坐标系变换与一些可视化工具的应用

    TF坐标在ROS中是一个非常重要的概念 因为机器人在做日常操作任务的时候 对于其所在位置和朝向是需要时刻知道的 而机器人是由很多节点组成的协同任务 对于每个部件 我们需要知道它的位姿 位置和朝向 这使得坐标系就成为了一个很重要的问题 TF的
  • Unity查找物体的方法总结

    文章目录 前言 一 不能找到失活对象的方法 1 Object类中的静态方法 2 GameObject类中的静态方法 二 能找到失活对象的方法 1 Transform Find 2 如何通过Transform找到自己以下的任意对象 总结 前言
  • JavaScript 判断空对象空数组

    JavaScript 判断空对象空数组 一 为什么判断空数组空对象会比较麻烦 二 判断空数组的方法 三 判定空对象的方法 四 一个判断参数为空的函数封装 来源 https www jianshu com p cadcbab793d7 我们判
  • ADAS的八大系统

    简述 ADAS Advanced Driving Assistant System 即高级驾驶辅助系统 ADAS 是利用安装于车上的各式各样的传感器 在第一时间收集车内外的环境数据 进行静 动态物体的辨识 侦测与追踪等技术上的处理 从而能够
  • Windows编程基础--第2节 win32程序资源管理

    操作系统 win10 64位 IDE vc 6 0 windows程序都有自己的资源 例如按钮 图标 对话框等等 这节介绍如何使用win32程序资源管理 1 继续使用上节的win32程序demo 执行File gt new添加资源 选择Fi
  • python爬虫返回403错误?加了请求头+代理也解决不了 >>看这

    一 问题分析 疑惑 使用python的requests库发起get或post请求返回403代码错误 使用postman发起请求发现状态码 lt 200 gt 竟然成功了 这是什么原因 首先排除ip问题 ip有问题的话postman也访问不了
  • 阿里技术副总裁贾扬清、微软 CTO 韦青重磅出席 AI 开发者大会!

    整理 夕颜 硬核 AI 技术大会 一年参加一次就够了 9 月 6日 7 日 2019 AI 开发者大会 AI ProCon 将在北京富力万丽酒店举行 人工智能领域技术领袖将再次齐聚一堂 共同探讨过去一年最新的 AI 技术趋势与变化 带你跟上
  • 【PytorchLearning】基于 UNet 的肺部影像语义分割案例保姆教程

    基于 UNet 的肺部影像分割 一般而言 计算机视觉领域包含三大主流任务 分类 检测 分割 其中 分类任务对模型的要求较为简单 在之前的Pytorch入门教程中已进行了较为详尽的介绍 有兴趣的小伙伴可以查看之前的博客 而检测和分割任务是比较
  • 一名全栈工程师的技术实践之路

    一 前言 1 1 什么是全栈 全栈开发是指开发人员掌握了前端 后端以及数据库等多个领域的知识和技能 能够独立完成整个项目的开发工作 在需求交付过程中 可以负责从项目的前期分析 设计到后期开发 测试 发布等整个过程 能够快速定位和解决问题 提
  • Graph 在项目中的实践

    前言 graph 图这种结构在项目中其实经常能够遇见 java 其实提供 jgrapht core 包来进行核心功能的实现 这里就使用jgrapht core 来对常见应用场景进行扩展 实现 1 引入依赖xml
  • Python爬虫 网页请求的异常处理

    网页请求的异常处理主要有两大类 urllib error URLError 用于捕获由urllib request产生的异常 使用reason属性返回错误原因 urllib error HTTPError 用于处理HTTP与HTTPS请求的
  • sql语句百万级千万级数据量分页

    在开发系统时难免会遇见分页的列表查询 针对小数据量我们可以查询的时间可以忽略不记 但针对百万级别千万级别的数据量时改怎么优化查询语句呢 该如果使用分页呢 下面总结几点 适量增加索引 在经常查询的字段上 尽量避免like in is null
  • Pycharm配置解释器(interpreter)

    关于pycharm编译器的解释器 网友朋友的分享 Pycharm配置 1 解释器 interpreter 详细了解PyCharm支持的4种Python Interpreter和配置方法 对大多数人而言就只需要 分清虚拟解释器和系统解释器 使
  • 二叉树采用二叉链表存储,求树的结点个数

    typedef struct BiTNode ElemType data struct BiTNode lchild rchild BiTNode BiTree void PrePrder BiTree T int num if T NUL
  • [leetcode 周赛 148] 1146 快照数组

    目录 1146 Snapshot Array 快照数组 描述 思路 代码实现 1146 Snapshot Array 快照数组 描述 实现支持下列接口的 快照数组 SnapshotArray SnapshotArray int length
  • nginx关于add_header的坑

    一 add header指令不会去重 nginx做反向代理时 如果后端返回的response中已经有该header头 则通过add header后会返回给客户端两个同样的header头 场景1 nginxA作为反向代理 nginxB作为we