128 lines
3.4 KiB
Lua
128 lines
3.4 KiB
Lua
local isempty = require "table.isempty"
|
|
local mime_type = require "kong.tools.mime_type"
|
|
|
|
|
|
local kong = kong
|
|
local type = type
|
|
local match = string.match
|
|
local noop = function() end
|
|
local parse_mime_type = mime_type.parse_mime_type
|
|
local mime_type_includes = mime_type.includes
|
|
local isplitn = require("kong.tools.string").isplitn
|
|
local strip = require("kong.tools.string").strip
|
|
|
|
|
|
local _M = {}
|
|
|
|
|
|
local function iter(config_array)
|
|
if type(config_array) ~= "table" then
|
|
return noop
|
|
end
|
|
|
|
return function(config_array, i)
|
|
i = i + 1
|
|
|
|
local header_to_test = config_array[i]
|
|
if header_to_test == nil then -- n + 1
|
|
return nil
|
|
end
|
|
|
|
local header_to_test_name, header_to_test_value = match(header_to_test, "^([^:]+):*(.-)$")
|
|
if header_to_test_value == "" then
|
|
header_to_test_value = nil
|
|
end
|
|
|
|
return i, header_to_test_name, header_to_test_value
|
|
end, config_array, 0
|
|
end
|
|
|
|
|
|
local function is_json_body(content_type)
|
|
if not content_type then
|
|
return false
|
|
end
|
|
local expected_media_type = { type = "application", subtype = "json" }
|
|
for ct in isplitn(content_type, ",") do
|
|
local t, subtype = parse_mime_type(strip(ct))
|
|
if not t or not subtype then
|
|
goto continue
|
|
end
|
|
local media_type = { type = t, subtype = subtype }
|
|
if mime_type_includes(expected_media_type, media_type) then
|
|
return true
|
|
end
|
|
::continue::
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
|
|
local function is_body_transform_set(conf)
|
|
return not isempty(conf.add.json ) or
|
|
not isempty(conf.rename.json ) or
|
|
not isempty(conf.remove.json ) or
|
|
not isempty(conf.replace.json) or
|
|
not isempty(conf.append.json )
|
|
end
|
|
|
|
|
|
-- export utility functions
|
|
_M.is_json_body = is_json_body
|
|
_M.is_body_transform_set = is_body_transform_set
|
|
|
|
|
|
---
|
|
-- # Example:
|
|
-- ngx.headers = header_filter.transform_headers(conf, ngx.headers)
|
|
-- We run transformations in following order: remove, rename, replace, add, append.
|
|
-- @param[type=table] conf Plugin configuration.
|
|
-- @param[type=table] ngx_headers Table of headers, that should be `ngx.headers`
|
|
-- @return table A table containing the new headers.
|
|
function _M.transform_headers(conf, headers)
|
|
local clear_header = kong.response.clear_header
|
|
local set_header = kong.response.set_header
|
|
local add_header = kong.response.add_header
|
|
|
|
-- remove headers
|
|
for _, header_name in iter(conf.remove.headers) do
|
|
clear_header(header_name)
|
|
end
|
|
|
|
-- rename headers(s)
|
|
for _, old_name, new_name in iter(conf.rename.headers) do
|
|
if headers[old_name] ~= nil and new_name then
|
|
local value = headers[old_name]
|
|
set_header(new_name, value)
|
|
clear_header(old_name)
|
|
end
|
|
end
|
|
|
|
-- replace headers
|
|
for _, header_name, header_value in iter(conf.replace.headers) do
|
|
if headers[header_name] ~= nil and header_value then
|
|
set_header(header_name, header_value)
|
|
end
|
|
end
|
|
|
|
-- add headers
|
|
for _, header_name, header_value in iter(conf.add.headers) do
|
|
if headers[header_name] == nil and header_value then
|
|
set_header(header_name, header_value)
|
|
end
|
|
end
|
|
|
|
-- append headers
|
|
for _, header_name, header_value in iter(conf.append.headers) do
|
|
add_header(header_name, header_value)
|
|
end
|
|
|
|
-- Removing the content-length header because the body is going to change
|
|
if is_body_transform_set(conf) and is_json_body(headers["Content-Type"]) then
|
|
clear_header("Content-Length")
|
|
end
|
|
end
|
|
|
|
return _M
|