需求
不修改代碼的情況下,在nginx轉發請求時修改response body獲取期望值。
請求有2個特徵唯一定位:
- url:/aaa/bbb/ccc/ddd
- 自定義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.com
與 456.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