Skip to content

Commit 4ebbcac

Browse files
committed
Add headers policy
1 parent 0afb648 commit 4ebbcac

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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 add_request_header(header, value, req_headers)
29+
local new_value = new_header_value(req_headers[header], value)
30+
ngx.req.set_header(header, new_value)
31+
end
32+
33+
local function set_request_header(header, value)
34+
ngx.req.set_header(header, value)
35+
end
36+
37+
local function push_request_header(header, value, req_headers)
38+
if req_headers[header] then
39+
add_request_header(header, value, req_headers)
40+
end
41+
end
42+
43+
local function add_resp_header(header, value)
44+
local new_value = new_header_value(ngx.header[header], value)
45+
ngx.header[header] = new_value
46+
end
47+
48+
local function set_resp_header(header, value)
49+
ngx.header[header] = value
50+
end
51+
52+
local function push_resp_header(header, value)
53+
if ngx.header[header] then
54+
add_resp_header(header, value)
55+
end
56+
end
57+
58+
local command_functions = {
59+
request = {
60+
add = add_request_header,
61+
set = set_request_header,
62+
push = push_request_header
63+
},
64+
response = {
65+
add = add_resp_header,
66+
set = set_resp_header,
67+
push = push_resp_header
68+
}
69+
}
70+
71+
-- header_type can be 'request' or 'response'.
72+
local function run_commands(commands, header_type)
73+
-- This is here to avoid calling ngx.req.get_headers() in every command
74+
-- applied to the request headers.
75+
local req_headers = {}
76+
if header_type == 'request' then
77+
req_headers = ngx.req.get_headers() or {}
78+
end
79+
80+
for _, command in ipairs(commands) do
81+
local command_func = command_functions[header_type][command.op]
82+
command_func(command.header, command.value, req_headers)
83+
end
84+
end
85+
86+
-- Initialize the config so we do not have to check for nulls in the rest of
87+
-- the code.
88+
local function init_config(config)
89+
local res = config or {}
90+
res.request = res.request or {}
91+
res.response = res.response or {}
92+
return res
93+
end
94+
95+
--- Initialize a Headers policy
96+
-- @tparam[opt] table config
97+
-- @field[opt] request Table with the operations to apply to the request headers
98+
-- @field[opt] response Table with the operations to apply to the response headers
99+
-- Each operation is a table with three elements:
100+
-- 1) op: can be 'add', 'set' or 'push'.
101+
-- 2) header
102+
-- 3) value
103+
-- The add operation:
104+
-- 1) When the header is not set, creates it with the given value.
105+
-- 2) When the header is set, it creates a new header with the same name and
106+
-- the given value.
107+
-- The set operation:
108+
-- 1) When the header is not set, creates it with the given value.
109+
-- 2) When the header is set, replaces its value with the given one.
110+
-- 3) Deletes a header when the value is "".
111+
-- The push operation:
112+
-- 1) When the header is not set, it does nothing.
113+
-- 2) When the header is set, it creates a new header with the same name and
114+
-- the given value.
115+
function _M.new(config)
116+
local self = new()
117+
self.config = init_config(config)
118+
return self
119+
end
120+
121+
function _M:rewrite()
122+
run_commands(self.config.request, 'request')
123+
end
124+
125+
function _M:header_filter()
126+
run_commands(self.config.response, 'response')
127+
end
128+
129+
return _M

0 commit comments

Comments
 (0)