1

需求

不修改代码的情况下,在nginx转发请求时修改response body获取期望值。

请求有2个特征唯一定位:

  1. url:/aaa/bbb/ccc/ddd
  2. 自定义header(区分版本):System-Version: pro 不同版本会请求相同服务器下相同url

Tip:这么干的原因主要是由于上线管控,问题修复后不能随时上线。但是线上部分用户已经不能正常使用功能了,所以算是一个暂时解决方案,不提倡不鼓励这么干哇~

原返回值:

{
  "code": 200,
  "data": {
    "deployAdmin": false,
    "systemId": "aaa"
  }
}

期望返回值:

// deployAdmin控制页面显示,这里期望为true
{
  "code": 200,
  "data": {
    "deployAdmin": true,
    "systemId": "aaa"
  }
}

实现

基于基本nginx配置,不需安装额外模块(安装额外模块得找运维,也赶不及-_-)。

读取自定义header

首先,开启underscores_in_headers

解释:HTTP头部是否允许下划线。默认为off,表示HTTP头部的名称中不允许带“_”
语法:underscores_in_headers on | off;
默认:underscores_in_headers off;
配置块:http、server

然后,通过$http_加自定义header读取目标请求头(纯小写,中划线替换为下划线)
比如:获取 System-Version 应写为 $http_system_version

# nginx.conf
server {
    listen          80;
    ...
    underscores_in_headers on;  
    ...
    location ~ ^/aaa/ {
        ... 
        if ($http_system_version = "pro") {
            ...
        }
    }
}

撰写AND条件

nginx配置中使用 if(a && b) 的条件判断是无效的。但需求中要求的条件是 url = '/aaa/bbb/ccc/ddd' 并且 $http_system_version = 'pro' 。解决思路是声明一个变量,每判断一个条件为true,就将变量修改一下,最后直接判断该变量是否达到了所有条件为true的修改状态即可。

# nginx.conf

location ~ ^/aaa/ {
    ...
    
    set $a 0;
    if ($http_system_version = "pro"){
        set $a 1;
    }
    if ($request_uri ~ ^/aaa/bbb/ccc/ddd) {
        set $a 1$a;
    }
    if ($a = '11') {
        ... 
    }
}

修改响应体

直接上这段逻辑完整配置

location ~ ^/aaa/ {
    # 以/aaa开头的请求代理到 http://xxx.yyy.com
    proxy_pass http://xxx.yyy.com;
    proxy_redirect          off; 
    proxy_set_header        X-Real-IP       $remote_addr; 
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    
    # AND条件判断变量
    set $a 0;
    # 请求中自定义header头System-Version为"pro"
    if ($http_system_version = "pro") {
        set $a 1;
    }
    # 请求url为'/aaa/bbb/ccc/ddd'
    if ($request_uri ~ ^/aaa/bbb/ccc/ddd) {
        set $a 1$a;
    }
    # 两个条件都符合时return 期望返回值
    if ($a = '11') {
        return 200 '{"code":200,"data":{"deployAdmin":true,"systemId":"aaa"}}';
    }
}

Tip: if后一定要跟空格,不然nginx会报错~

域名重定向

小记一下,跟本次需求无关联

服务器对应两个域名123.yy.com456.yy.com,用户访问123.yy.com时,将请求重定向到456.yy.com(此时浏览器地址栏url域名会被替换)。这种情况适用与新老域名过渡期~

if ($host = '123.yy.com') {
    rewrite ^/(.*)$ http://456.yy.com/$1 permanent;
}

小记

有一个过滤器模块 ngx_http_sub_module,它可以通过将一个指定的字符串替换为另一个字符串来响应,但需要安装,默认不带。

另:更灵活的配置可通过搭配lua


沐乃
102 声望20 粉丝

The outer world you see is a reflection of your inner self.