Skip to content

Commit 62eb4d0

Browse files
authored
feat: support add custom headers for etcd requests (#143)
1 parent 1243bf4 commit 62eb4d0

File tree

4 files changed

+216
-4
lines changed

4 files changed

+216
-4
lines changed

api_v3.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Method
4444
- `ssl_cert_path`: string - path to the client certificate
4545
- `ssl_key_path`: string - path to the client key
4646
- `serializer`: string - serializer type, default `json`, also support `raw` to keep origin string value.
47+
- `extra_headers`: table - adding custom headers for etcd requests.
4748

4849
The client method returns either a `etcd` object or an `error string`.
4950

lib/resty/etcd/v3.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ local sub_str = string.sub
1212
local str_byte = string.byte
1313
local str_char = string.char
1414
local ipairs = ipairs
15+
local pairs = pairs
1516
local re_match = ngx.re.match
1617
local type = type
1718
local tab_insert = table.insert
19+
local str_lower = string.lower
1820
local tab_clone = require("table.clone")
1921
local decode_json = cjson.decode
2022
local encode_json = cjson.encode
@@ -28,6 +30,15 @@ local _M = {}
2830

2931
local mt = { __index = _M }
3032

33+
local unmodifiable_headers = {
34+
["authorization"] = true,
35+
["content-length"] = true,
36+
["transfer-encoding"] = true,
37+
["connection"] = true,
38+
["upgrade"] = true,
39+
}
40+
41+
3142
-- define local refresh function variable
3243
local refresh_jwt_token
3344

@@ -125,6 +136,15 @@ local function _request_uri(self, method, uri, opts, timeout, ignore_auth)
125136
end
126137
end
127138

139+
if self.extra_headers and type(self.extra_headers) == "table" then
140+
for key, value in pairs(self.extra_headers) do
141+
if not unmodifiable_headers[str_lower(key)] then
142+
headers[key] = value
143+
end
144+
end
145+
utils.log_info("request uri headers: ", encode_json(headers))
146+
end
147+
128148
local http_cli, err = utils.http.new()
129149
if err then
130150
return nil, err
@@ -187,6 +207,7 @@ function _M.new(opts)
187207
ssl_verify = true
188208
end
189209
local serializer = opts.serializer
210+
local extra_headers = opts.extra_headers
190211

191212
if not typeof.uint(timeout) then
192213
return nil, 'opts.timeout must be unsigned integer'
@@ -264,6 +285,7 @@ function _M.new(opts)
264285

265286
ssl_cert_path = opts.ssl_cert_path,
266287
ssl_key_path = opts.ssl_key_path,
288+
extra_headers = extra_headers,
267289
},
268290
mt)
269291
end
@@ -604,6 +626,15 @@ local function request_chunk(self, method, path, opts, timeout)
604626
headers.Authorization = self.jwt_token
605627
end
606628

629+
if self.extra_headers and type(self.extra_headers) == "table" then
630+
for key, value in pairs(self.extra_headers) do
631+
if not unmodifiable_headers[str_lower(key)] then
632+
headers[key] = value
633+
end
634+
end
635+
utils.log_info("request chunk headers: ", encode_json(headers))
636+
end
637+
607638
local http_cli
608639
http_cli, err = utils.http.new()
609640
if err then

t/v3/auth.t

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,93 @@ v3 refresh jwt last err: connection refused
211211
connection refused
212212
v3 refresh jwt last err: connection refused
213213
connection refused
214+
215+
216+
217+
=== TEST 4: Authorization header will not be overridden when etcd auth is enabled(request uri)
218+
--- http_config eval: $::HttpConfig
219+
--- config
220+
location /t {
221+
content_by_lua_block {
222+
local etcd, err = require "resty.etcd" .new({
223+
protocol = "v3",
224+
user = 'root',
225+
password = 'abc123',
226+
timeout = 3,
227+
http_host = {
228+
"http://127.0.0.1:12379",
229+
},
230+
extra_headers = {
231+
Authorization = "bar",
232+
},
233+
})
234+
check_res(etcd, err)
235+
local res, err = etcd:set("/test", { a='abc'})
236+
check_res(res, err)
237+
ngx.say('ok')
238+
}
239+
}
240+
--- request
241+
GET /t
242+
--- no_error_log
243+
[error]
244+
--- response_body
245+
ok
246+
247+
248+
249+
=== TEST 5: Authorization header will not be overridden when etcd auth is enabled(request chunk)
250+
--- http_config eval: $::HttpConfig
251+
--- config
252+
location /t {
253+
content_by_lua_block {
254+
local etcd, err = require "resty.etcd" .new({
255+
protocol = "v3",
256+
user = 'root',
257+
password = 'abc123',
258+
timeout = 3,
259+
http_host = {
260+
"http://127.0.0.1:12379",
261+
},
262+
extra_headers = {
263+
Authorization = "bar",
264+
},
265+
})
266+
local res, err = etcd:set("/test", "abc")
267+
check_res(res, err)
268+
269+
ngx.timer.at(0.1, function ()
270+
etcd:set("/test", "bcd3")
271+
end)
272+
273+
local cur_time = ngx.now()
274+
local body_chunk_fun, err = etcd:watch("/test", {timeout = 0.5})
275+
if not body_chunk_fun then
276+
ngx.say("failed to watch: ", err)
277+
end
278+
279+
local idx = 0
280+
while true do
281+
local chunk, err = body_chunk_fun()
282+
283+
if not chunk then
284+
if err then
285+
ngx.say(err)
286+
end
287+
break
288+
end
289+
290+
idx = idx + 1
291+
ngx.say(idx, ": ", require("cjson").encode(chunk.result))
292+
end
293+
}
294+
}
295+
--- request
296+
GET /t
297+
--- no_error_log
298+
[error]
299+
--- response_body_like eval
300+
qr/1:.*"created":true.*
301+
2:.*"value":"bcd3".*
302+
timeout/
303+
--- timeout: 5

t/v3/key.t

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ timeout/
284284
--- timeout: 5
285285
286286
287-
=== TEST 4.1: watchdir(key=="")
287+
288+
=== TEST 6: watchdir(key=="")
288289
--- http_config eval: $::HttpConfig
289290
--- config
290291
location /t {
@@ -348,7 +349,7 @@ timeout/
348349
349350
350351
351-
=== TEST 6: setx(key, val) failed
352+
=== TEST 7: setx(key, val) failed
352353
--- http_config eval: $::HttpConfig
353354
--- config
354355
location /t {
@@ -369,7 +370,7 @@ GET /t
369370
370371
371372
372-
=== TEST 7: setx(key, val) success
373+
=== TEST 8: setx(key, val) success
373374
--- http_config eval: $::HttpConfig
374375
--- config
375376
location /t {
@@ -395,7 +396,7 @@ checked val as expect: abd
395396
396397
397398
398-
=== TEST 8: setnx(key, val)
399+
=== TEST 9: setnx(key, val)
399400
--- http_config eval: $::HttpConfig
400401
--- config
401402
location /t {
@@ -422,3 +423,92 @@ GET /t
422423
[error]
423424
--- response_body
424425
checked val as expect: aaa
426+
427+
428+
429+
=== TEST 10: set extra_headers for request_uri
430+
--- http_config eval: $::HttpConfig
431+
--- config
432+
location /t {
433+
content_by_lua_block {
434+
local etcd, err = require "resty.etcd" .new({
435+
protocol = "v3",
436+
extra_headers = {
437+
foo = "bar",
438+
}
439+
})
440+
check_res(etcd, err)
441+
442+
local res, err = etcd:set("/test", "abc", {prev_kv = true})
443+
check_res(res, err)
444+
445+
local data, err = etcd:get("/test")
446+
check_res(data, err, "abc")
447+
}
448+
}
449+
--- request
450+
GET /t
451+
--- no_error_log
452+
[error]
453+
--- response_body
454+
checked val as expect: abc
455+
--- error_log
456+
request uri headers: {"foo":"bar"}
457+
458+
459+
460+
=== TEST 11: Authorization header will not be overridden
461+
--- http_config eval: $::HttpConfig
462+
--- config
463+
location /t {
464+
content_by_lua_block {
465+
local etcd, err = require "resty.etcd" .new({
466+
protocol = "v3",
467+
extra_headers = {
468+
Authorization = "bar",
469+
}
470+
})
471+
check_res(etcd, err)
472+
473+
local res, err = etcd:set("/test", "abc", {prev_kv = true})
474+
check_res(res, err)
475+
476+
local data, err = etcd:get("/test")
477+
check_res(data, err, "abc")
478+
}
479+
}
480+
--- request
481+
GET /t
482+
--- no_error_log
483+
[error]
484+
--- response_body
485+
checked val as expect: abc
486+
--- error_log
487+
request uri headers: {}
488+
489+
490+
491+
=== TEST 12: set extra_headers for request_chunk
492+
--- http_config eval: $::HttpConfig
493+
--- config
494+
location /t {
495+
content_by_lua_block {
496+
local etcd, err = require "resty.etcd" .new({
497+
protocol = "v3",
498+
extra_headers = {
499+
foo = "bar",
500+
}
501+
})
502+
local res, err = etcd:set("/test", "abc")
503+
local body_chunk_fun, _ = etcd:watch("/test", {timeout = 0.5})
504+
ngx.say("passed")
505+
}
506+
}
507+
--- request
508+
GET /t
509+
--- response_body
510+
passed
511+
--- error_log
512+
request chunk headers: {"foo":"bar"}
513+
--- no_error_log
514+
[error]

0 commit comments

Comments
 (0)