Nginx querystring 轉寫的兩個例子

題葉發表於2023-01-16

轉發請求時需要兩個功能, 一個是去掉 querystring 上特定的欄位, 一個是替換掉一個欄位的值.

參考兩篇文章得到一個可用的方案,

https://itecnotes.com/server/...
https://zzyongx.github.io/blo...

主要的思路是透過正則, 對 $args 反覆進行替換, 得到自己想要的結果,

upstream myhost {
  server myupstream.com:443;
}

# 強制 log 輸出到 stdout
access_log /dev/stdout;
error_log /dev/stderr info;

server {
  listen 5555;

  location /my/api {

    # 目前介面都轉發到該域名
    set $target_host "myupstream.com";
    # set $target_host REPLACED_HOST;

    set $target_data "REPLACED_DATA";
    # set $target_data "dev";

    # 正則處理的不是資料結構, 各種組合需要手動遍歷

    # 去掉後邊的 extraKey
    if ( $args ~* ^(.*)&extraKey=[\w\d]+(.*)$ ) {
      set $args $1$2;
    }
    # 去掉開頭的 extraKey
    if ( $args ~* ^extraKey=[\w\d]+(.*)$ ) {
      set $args $2;
    }
    # 清除 myData
    if ( $args ~* ^(.*)&myData=\w+(.*)$ ) {
      set $args $1$2;
    }
    # 清除開頭的 myData
    if ( $args ~* ^myData=\w+(.*)$ ) {
      set $args $1;
    }

    # 清除後設定一個指定一個引數
    set $arg_myData "$target_data";
    
    proxy_set_header Host $target_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # proxy_set_header X-Real-IP $remote_addr;
    proxy_pass_request_headers on;

    # HTTP 轉 HTTPS 用
    proxy_ssl_server_name on;

    set $args "$args&myData=$arg_myData";

    # 除錯用
    # return 200 "$target_host/api$uri$is_args$args&myData=$arg_myData";
    proxy_pass https://myhost/api$uri$is_args$args;
  }
}

注意 $arg_myData 雖然是從 querystring 解析出來的 field, 但是修改了只會增加, 而不是替換. 直接增加可能出現兩個 myData 的請求, 不能保證伺服器解析和處理都是對的. 所以應該是先清除, 再自己加上.

功能不難, 除錯時報錯不夠透明, 一搬用 return 200 "content"; 強行返回檢視. 其他看不到的中間過程只能儘量抓出來看了.

相關文章