Skip to content

Commit

Permalink
fix(pdk): response.set_header support header argument with table arra…
Browse files Browse the repository at this point in the history
…y of string (#12164)

This PR lets response.set_header support setting a header with an array of strings. It also fixes a type error issue in the response-header-transformer plugin when manipulating multiple headers with the same name.

FTI-5585
  • Loading branch information
oowl authored Dec 25, 2023
1 parent 6fe6813 commit 2b99ee7
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message: "response.set_header support header argument with table array of string"
type: bugfix
scope: PDK
12 changes: 10 additions & 2 deletions kong/pdk/private/checks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@ function checks.validate_header(name, value)

local tvalue = type(value)
if tvalue ~= "string" then
if tvalue == "number" or tvalue == "boolean" then
if tvalue == "table" then
for _, vv in ipairs(value) do
local tvv = type(vv)
if tvv ~= "string" then
error(fmt("invalid header value in array %q: got %s, " ..
"expected string", name, tvv), 3)
end
end
elseif tvalue == "number" or tvalue == "boolean" then
value = tostring(value)
else
error(fmt("invalid header value for %q: got %s, expected " ..
"string, number or boolean", name, tvalue), 3)
"array of string, string, number or boolean", name, tvalue), 3)
end
end
return value
Expand Down
5 changes: 2 additions & 3 deletions kong/pdk/response.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ local error = error
local pairs = pairs
local coroutine = coroutine
local cjson_encode = cjson.encode
local normalize_header = checks.normalize_header
local normalize_multi_header = checks.normalize_multi_header
local validate_header = checks.validate_header
local validate_headers = checks.validate_headers
Expand Down Expand Up @@ -431,7 +430,7 @@ local function new(self, major_version)
return
end

ngx.header[name] = normalize_header(value)
ngx.header[name] = normalize_multi_header(value)
end


Expand Down Expand Up @@ -463,7 +462,7 @@ local function new(self, major_version)

validate_header(name, value)

add_header(name, normalize_header(value))
add_header(name, normalize_multi_header(value))
end


Expand Down
5 changes: 2 additions & 3 deletions kong/pdk/service/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ local string_find = string.find
local string_sub = string.sub
local string_byte = string.byte
local string_lower = string.lower
local normalize_header = checks.normalize_header
local normalize_multi_header = checks.normalize_multi_header
local validate_header = checks.validate_header
local validate_headers = checks.validate_headers
Expand Down Expand Up @@ -312,7 +311,7 @@ local function new(self)
end
end

ngx.req.set_header(header, normalize_header(value))
ngx.req.set_header(header, normalize_multi_header(value))
end

---
Expand Down Expand Up @@ -343,7 +342,7 @@ local function new(self)
headers = { headers }
end

table_insert(headers, normalize_header(value))
table_insert(headers, normalize_multi_header(value))

ngx.req.set_header(header, headers)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ describe("Plugin: response-transformer", function()
header_transformer.transform_headers(conf, headers)
assert.same({}, headers)
end)
it("header rename when same header being set twice", function()
local headers = get_headers({ h1 = { "v1", "v2"}})
header_transformer.transform_headers(conf, headers)
assert.same({h2 = { "v1", "v2" }}, headers)
end)
end)
describe("replace", function()
local conf = {
Expand Down
4 changes: 2 additions & 2 deletions t/01-pdk/06-service-request/09-set_header.t
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ invalid header name "127001": got number, expected string
--- request
GET /t
--- response_body
invalid header value for "foo": got function, expected string, number or boolean
invalid header value for "foo": got function, expected array of string, string, number or boolean
--- no_error_log
[error]
Expand All @@ -89,7 +89,7 @@ invalid header value for "foo": got function, expected string, number or boolean
--- request
GET /t
--- response_body
invalid header value for "foo": got nil, expected string, number or boolean
invalid header value for "foo": got nil, expected array of string, string, number or boolean
--- no_error_log
[error]
Expand Down
4 changes: 2 additions & 2 deletions t/01-pdk/06-service-request/10-add_header.t
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ invalid header name "127001": got number, expected string
--- request
GET /t
--- response_body
invalid header value for "foo": got function, expected string, number or boolean
invalid header value for "foo": got function, expected array of string, string, number or boolean
--- no_error_log
[error]
Expand All @@ -89,7 +89,7 @@ invalid header value for "foo": got function, expected string, number or boolean
--- request
GET /t
--- response_body
invalid header value for "foo": got nil, expected string, number or boolean
invalid header value for "foo": got nil, expected array of string, string, number or boolean
--- no_error_log
[error]
Expand Down
43 changes: 39 additions & 4 deletions t/01-pdk/08-response/05-set_header.t
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ invalid header name "127001": got number, expected string
=== TEST 3: response.set_header() errors if value is not a string
=== TEST 3: response.set_header() errors if value is not a table contain array of string
--- http_config eval: $t::Util::HttpConfig
--- config
location = /t {
Expand All @@ -89,8 +89,9 @@ invalid header name "127001": got number, expected string
local PDK = require "kong.pdk"
local pdk = PDK.new()
local set_header = { {} }
local ok, err = pcall(pdk.response.set_header, "foo", {})
local ok, err = pcall(pdk.response.set_header, "foo", set_header)
if not ok then
ngx.ctx.err = err
end
Expand All @@ -104,7 +105,7 @@ invalid header name "127001": got number, expected string
--- request
GET /t
--- response_body chop
invalid header value for "foo": got table, expected string, number or boolean
invalid header value in array "foo": got table, expected string
--- no_error_log
[error]
Expand Down Expand Up @@ -137,7 +138,7 @@ invalid header value for "foo": got table, expected string, number or boolean
--- request
GET /t
--- response_body chop
invalid header value for "foo": got nil, expected string, number or boolean
invalid header value for "foo": got nil, expected array of string, string, number or boolean
--- no_error_log
[error]
Expand Down Expand Up @@ -277,3 +278,37 @@ GET /t
Transfer-Encoding: chunked
--- error_log
manually setting Transfer-Encoding. Ignored.
=== TEST 8: response.set_header() with header table
--- http_config eval: $t::Util::HttpConfig
--- config
location = /t {
content_by_lua_block {
}
header_filter_by_lua_block {
ngx.header.content_length = nil
local PDK = require "kong.pdk"
local pdk = PDK.new()
local set_header = {"a", "b"}
pdk.response.set_header("X-Foo", set_header)
}
body_filter_by_lua_block {
local new_headers = ngx.resp.get_headers()
local cjson = require("cjson")
ngx.arg[1] = "X-Foo: {" .. new_headers["X-Foo"][1] .. "," .. new_headers["X-Foo"][2] .. "}"
ngx.arg[2] = true
}
}
--- request
GET /t
--- response_body chop
X-Foo: {a,b}
--- no_error_log
[error]
6 changes: 3 additions & 3 deletions t/01-pdk/08-response/06-add_header.t
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ invalid header name "127001": got number, expected string
local PDK = require "kong.pdk"
local pdk = PDK.new()
local ok, err = pcall(pdk.response.add_header, "foo", {})
local ok, err = pcall(pdk.response.add_header, "foo", {{}})
if not ok then
ngx.ctx.err = err
end
Expand All @@ -104,7 +104,7 @@ invalid header name "127001": got number, expected string
--- request
GET /t
--- response_body chop
invalid header value for "foo": got table, expected string, number or boolean
invalid header value in array "foo": got table, expected string
--- no_error_log
[error]
Expand Down Expand Up @@ -137,7 +137,7 @@ invalid header value for "foo": got table, expected string, number or boolean
--- request
GET /t
--- response_body chop
invalid header value for "foo": got nil, expected string, number or boolean
invalid header value for "foo": got nil, expected array of string, string, number or boolean
--- no_error_log
[error]
Expand Down

0 comments on commit 2b99ee7

Please sign in to comment.