From 0789f10dafc519999b788aae66f763cdda4399fa Mon Sep 17 00:00:00 2001 From: spacewander Date: Fri, 7 May 2021 12:25:47 +0800 Subject: [PATCH 1/2] feat(reponse-rewrite): allow using variable in the header Fix #3727 Signed-off-by: spacewander --- apisix/plugins/response-rewrite.lua | 3 +- docs/en/latest/plugins/response-rewrite.md | 6 ++- docs/zh/latest/plugins/response-rewrite.md | 6 ++- t/plugin/response-rewrite.t | 52 ++++++++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index b415c7c28e31..2f767bca33b4 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -168,7 +168,8 @@ function _M.header_filter(conf, ctx) local field_cnt = #conf.headers_arr for i = 1, field_cnt, 2 do - ngx.header[conf.headers_arr[i]] = conf.headers_arr[i+1] + local val = core.utils.resolve_var(conf.headers_arr[i+1], ctx.var) + ngx.header[conf.headers_arr[i]] = val end end diff --git a/docs/en/latest/plugins/response-rewrite.md b/docs/en/latest/plugins/response-rewrite.md index f95d6a349968..a8c6b85e7586 100644 --- a/docs/en/latest/plugins/response-rewrite.md +++ b/docs/en/latest/plugins/response-rewrite.md @@ -46,7 +46,7 @@ response rewrite plugin, rewrite the content returned by the upstream as well as | status_code | integer | optional | | [200, 598] | New `status code` to client, keep the original response code by default. | | body | string | optional | | | New `body` to client, and the content-length will be reset too. | | body_base64 | boolean | optional | false | | Identify if `body` in configuration need base64 decoded before rewrite to client. | -| headers | object | optional | | | Set the new `headers` for client, can set up multiple. If it exists already from upstream, will rewrite the header, otherwise will add the header. You can set the corresponding value to an empty string to remove a header. | +| headers | object | optional | | | Set the new `headers` for client, can set up multiple. If it exists already from upstream, will rewrite the header, otherwise will add the header. You can set the corresponding value to an empty string to remove a header. The value can contain Nginx variable in `$var` format, like `$remote_addr $balancer_ip` | | vars | array[] | optional | | | A DSL to evaluate with the given ngx.var. See `vars` [lua-resty-expr](https://github.com/api7/lua-resty-expr#operator-list). if the `vars` is empty, then all rewrite operations will be executed unconditionally | ## How To Enable @@ -63,7 +63,8 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f1 "body": "{\"code\":\"ok\",\"message\":\"new json body\"}", "headers": { "X-Server-id": 3, - "X-Server-status": "on" + "X-Server-status": "on", + "X-Server-balancer_addr": "$balancer_ip:$balancer_port" }, "vars":[ [ "status","==","200" ] @@ -97,6 +98,7 @@ Transfer-Encoding: chunked Connection: keep-alive X-Server-id: 3 X-Server-status: on +X-Server-balancer_addr: 127.0.0.1:80 {"code":"ok","message":"new json body"} ``` diff --git a/docs/zh/latest/plugins/response-rewrite.md b/docs/zh/latest/plugins/response-rewrite.md index bc352bd4855a..85a03783478f 100644 --- a/docs/zh/latest/plugins/response-rewrite.md +++ b/docs/zh/latest/plugins/response-rewrite.md @@ -45,7 +45,7 @@ title: response-rewrite | status_code | integer | 可选 | | [200, 598] | 修改上游返回状态码,默认保留原始响应代码。 | | body | string | 可选 | | | 修改上游返回的 `body` 内容,如果设置了新内容,header 里面的 content-length 字段也会被去掉 | | body_base64 | boolean | 可选 | false | | 描述 `body` 字段是否需要 base64 解码之后再返回给客户端,用在某些图片和 Protobuffer 场景 | -| headers | object | 可选 | | | 返回给客户端的 `headers`,这里可以设置多个。头信息如果存在将重写,不存在则添加。想要删除某个 header 的话,把对应的值设置为空字符串即可 | +| headers | object | 可选 | | | 返回给客户端的 `headers`,这里可以设置多个。头信息如果存在将重写,不存在则添加。想要删除某个 header 的话,把对应的值设置为空字符串即可。这个值能够以 `$var` 的格式包含 Nginx 变量,比如 `$remote_addr $balancer_ip` | | vars | array[] | 可选 | | | `vars` 是一个表达式列表,只有满足条件的请求和响应才会修改 body 和 header 信息,来自 [lua-resty-expr](https://github.com/api7/lua-resty-expr#operator-list)。如果 `vars` 字段为空,那么所有的重写动作都会被无条件的执行。 | ## 示例 @@ -64,7 +64,8 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f1 "body": "{\"code\":\"ok\",\"message\":\"new json body\"}", "headers": { "X-Server-id": 3, - "X-Server-status": "on" + "X-Server-status": "on", + "X-Server-balancer_addr": "$balancer_ip:$balancer_port" }, "vars":[ [ "status","==","200" ] @@ -97,6 +98,7 @@ Transfer-Encoding: chunked Connection: keep-alive X-Server-id: 3 X-Server-status: on +X-Server-balancer_addr: 127.0.0.1:80 {"code":"ok","message":"new json body"} ``` diff --git a/t/plugin/response-rewrite.t b/t/plugin/response-rewrite.t index d1f23a9853eb..b716ea6de4b9 100644 --- a/t/plugin/response-rewrite.t +++ b/t/plugin/response-rewrite.t @@ -676,3 +676,55 @@ GET /t invalid base64 content --- no_error_log [error] + + + +=== TEST 24: rewrite header with variable +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "response-rewrite": { + "headers" : { + "X-A": "$remote_addr", + "X-B": "from $remote_addr to $balancer_ip:$balancer_port" + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/with_header" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 25: hit +--- request +GET /with_header +--- response_headers +X-A: 127.0.0.1 +X-B: from 127.0.0.1 to 127.0.0.1:1980 +--- no_error_log +[error] From eadc55199c2347972abc7264a086f87f2cb79302 Mon Sep 17 00:00:00 2001 From: spacewander Date: Sat, 8 May 2021 08:56:17 +0800 Subject: [PATCH 2/2] tweak Signed-off-by: spacewander --- docs/en/latest/plugins/response-rewrite.md | 2 +- t/plugin/response-rewrite.t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/latest/plugins/response-rewrite.md b/docs/en/latest/plugins/response-rewrite.md index a8c6b85e7586..a05dbdaf71db 100644 --- a/docs/en/latest/plugins/response-rewrite.md +++ b/docs/en/latest/plugins/response-rewrite.md @@ -46,7 +46,7 @@ response rewrite plugin, rewrite the content returned by the upstream as well as | status_code | integer | optional | | [200, 598] | New `status code` to client, keep the original response code by default. | | body | string | optional | | | New `body` to client, and the content-length will be reset too. | | body_base64 | boolean | optional | false | | Identify if `body` in configuration need base64 decoded before rewrite to client. | -| headers | object | optional | | | Set the new `headers` for client, can set up multiple. If it exists already from upstream, will rewrite the header, otherwise will add the header. You can set the corresponding value to an empty string to remove a header. The value can contain Nginx variable in `$var` format, like `$remote_addr $balancer_ip` | +| headers | object | optional | | | Set the new `headers` for client, can set up multiple. If it exists already from upstream, will rewrite the header, otherwise will add the header. You can set the corresponding value to an empty string to remove a header. The value can contain Nginx variables in `$var` format, like `$remote_addr $balancer_ip` | | vars | array[] | optional | | | A DSL to evaluate with the given ngx.var. See `vars` [lua-resty-expr](https://github.com/api7/lua-resty-expr#operator-list). if the `vars` is empty, then all rewrite operations will be executed unconditionally | ## How To Enable diff --git a/t/plugin/response-rewrite.t b/t/plugin/response-rewrite.t index b716ea6de4b9..670e536798ef 100644 --- a/t/plugin/response-rewrite.t +++ b/t/plugin/response-rewrite.t @@ -679,7 +679,7 @@ invalid base64 content -=== TEST 24: rewrite header with variable +=== TEST 24: rewrite header with variables --- config location /t { content_by_lua_block {