Skip to content

Commit 2128033

Browse files
authored
Merge pull request #497 from 3scale/headers-policy
Add headers policy
2 parents 3063ce6 + cc54648 commit 2128033

File tree

2 files changed

+621
-0
lines changed

2 files changed

+621
-0
lines changed
+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
--- Headers policy
2+
-- This policy allows to include custom headers that will be sent to the
3+
-- upstream as well as modify or delete the ones included in the original
4+
-- request.
5+
-- Similarly, this policy also allows to add, modify, and delete the headers
6+
-- included in the response.
7+
8+
local ipairs = ipairs
9+
local type = type
10+
local insert = table.insert
11+
12+
local policy = require('apicast.policy')
13+
local _M = policy.new('Headers policy')
14+
15+
local new = _M.new
16+
17+
local function new_header_value(current_value, value_to_add)
18+
local new_value = current_value or {}
19+
20+
if type(new_value) == 'string' then
21+
new_value = { new_value }
22+
end
23+
24+
insert(new_value, value_to_add)
25+
return new_value
26+
end
27+
28+
local function push_request_header(header_name, value, req_headers)
29+
local new_value = new_header_value(req_headers[header_name], value)
30+
ngx.req.set_header(header_name, new_value)
31+
end
32+
33+
local function set_request_header(header_name, value)
34+
ngx.req.set_header(header_name, value)
35+
end
36+
37+
local function add_request_header(header_name, value, req_headers)
38+
if req_headers[header_name] then
39+
push_request_header(header_name, value, req_headers)
40+
end
41+
end
42+
43+
local function push_resp_header(header_name, value)
44+
local new_value = new_header_value(ngx.header[header_name], value)
45+
ngx.header[header_name] = new_value
46+
end
47+
48+
local function set_resp_header(header_name, value)
49+
ngx.header[header_name] = value
50+
end
51+
52+
local function add_resp_header(header_name, value)
53+
if ngx.header[header_name] then
54+
push_resp_header(header_name, value)
55+
end
56+
end
57+
58+
local command_functions = {
59+
request = {
60+
push = push_request_header,
61+
add = add_request_header,
62+
set = set_request_header
63+
},
64+
response = {
65+
push = push_resp_header,
66+
add = add_resp_header,
67+
set = set_resp_header
68+
}
69+
}
70+
71+
-- header_type can be 'request' or 'response'.
72+
local function run_commands(commands, header_type, ...)
73+
for _, command in ipairs(commands) do
74+
local command_func = command_functions[header_type][command.op]
75+
command_func(command.header, command.value, ...)
76+
end
77+
end
78+
79+
-- Initialize the config so we do not have to check for nulls in the rest of
80+
-- the code.
81+
local function init_config(config)
82+
local res = config or {}
83+
res.request = res.request or {}
84+
res.response = res.response or {}
85+
return res
86+
end
87+
88+
--- Initialize a Headers policy
89+
-- @tparam[opt] table config
90+
-- @field[opt] request Table with the operations to apply to the request headers
91+
-- @field[opt] response Table with the operations to apply to the response headers
92+
-- Each operation is a table with three elements:
93+
-- 1) op: can be 'add', 'set' or 'push'.
94+
-- 2) header
95+
-- 3) value
96+
-- The push operation:
97+
-- 1) When the header is not set, creates it with the given value.
98+
-- 2) When the header is set, it creates a new header with the same name and
99+
-- the given value.
100+
-- The set operation:
101+
-- 1) When the header is not set, creates it with the given value.
102+
-- 2) When the header is set, replaces its value with the given one.
103+
-- 3) Deletes a header when the value is "".
104+
-- The add operation:
105+
-- 1) When the header is not set, it does nothing.
106+
-- 2) When the header is set, it creates a new header with the same name and
107+
-- the given value.
108+
function _M.new(config)
109+
local self = new()
110+
self.config = init_config(config)
111+
return self
112+
end
113+
114+
function _M:rewrite()
115+
-- This is here to avoid calling ngx.req.get_headers() in every command
116+
-- applied to the request headers.
117+
local req_headers = ngx.req.get_headers() or {}
118+
run_commands(self.config.request, 'request', req_headers)
119+
end
120+
121+
function _M:header_filter()
122+
run_commands(self.config.response, 'response')
123+
end
124+
125+
return _M

0 commit comments

Comments
 (0)