mirror of
https://github.com/bjc/prosody.git
synced 2025-04-01 20:27:39 +03:00
util.http: Implement parser for RFC 7239 Forwarded header
Standardized and structured replacement for the X-Forwarded-For, X-Forwarded-Proto set of headers. Notably, this allows per-hop protocol information, unlike X-Forwarded-Proto which is always a single value for some reason.
This commit is contained in:
parent
517f20b523
commit
99906e5b9c
3 changed files with 55 additions and 0 deletions
|
@ -56,6 +56,7 @@
|
|||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6455"/>
|
||||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6901"/>
|
||||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7233"/>
|
||||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7239"/>
|
||||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7301"/>
|
||||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7395"/>
|
||||
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7590"/>
|
||||
|
|
|
@ -108,4 +108,25 @@ describe("util.http", function()
|
|||
assert.is_(http.contains_token("fo o", "foo"));
|
||||
end);
|
||||
end);
|
||||
|
||||
do
|
||||
describe("parse_forwarded", function()
|
||||
it("works", function()
|
||||
assert.same({ { ["for"] = "[2001:db8:cafe::17]:4711" } }, http.parse_forwarded('For="[2001:db8:cafe::17]:4711"'), "case insensitive");
|
||||
|
||||
assert.same({ { ["for"] = "192.0.2.60"; proto = "http"; by = "203.0.113.43" } }, http.parse_forwarded('for=192.0.2.60;proto=http;by=203.0.113.43'),
|
||||
"separated by semicolon");
|
||||
|
||||
assert.same({ { ["for"] = "192.0.2.43" }; { ["for"] = "198.51.100.17" } }, http.parse_forwarded('for=192.0.2.43, for=198.51.100.17'),
|
||||
"Values from multiple proxy servers can be appended using a comma");
|
||||
|
||||
end)
|
||||
it("rejects quoted quotes", function ()
|
||||
assert.falsy(http.parse_forwarded('foo="bar\"bar'), "quoted quotes");
|
||||
end)
|
||||
pending("deals with quoted quotes", function ()
|
||||
assert.same({ { foo = 'bar"baz' } }, http.parse_forwarded('foo="bar\"bar'), "quoted quotes");
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end);
|
||||
|
|
|
@ -69,9 +69,42 @@ local function normalize_path(path, is_dir)
|
|||
return path;
|
||||
end
|
||||
|
||||
--- Parse the RFC 7239 Forwarded header into array of key-value pairs.
|
||||
local function parse_forwarded(forwarded)
|
||||
if type(forwarded) ~= "string" then
|
||||
return nil;
|
||||
end
|
||||
|
||||
local fwd = {}; -- array
|
||||
local cur = {}; -- map, to which we add the next key-value pair
|
||||
for key, quoted, value, delim in forwarded:gmatch("(%w+)%s*=%s*(\"?)([^,;\"]+)%2%s*(.?)") do
|
||||
-- FIXME quoted quotes like "foo\"bar"
|
||||
-- unlikely when only dealing with IP addresses
|
||||
if quoted == '"' then
|
||||
value = value:gsub("\\(.)", "%1");
|
||||
end
|
||||
|
||||
cur[key:lower()] = value;
|
||||
if delim == "" or delim == "," then
|
||||
t_insert(fwd, cur)
|
||||
if delim == "" then
|
||||
-- end of the string
|
||||
break;
|
||||
end
|
||||
cur = {};
|
||||
elseif delim ~= ";" then
|
||||
-- misparsed
|
||||
return false;
|
||||
end
|
||||
end
|
||||
|
||||
return fwd;
|
||||
end
|
||||
|
||||
return {
|
||||
urlencode = urlencode, urldecode = urldecode;
|
||||
formencode = formencode, formdecode = formdecode;
|
||||
contains_token = contains_token;
|
||||
normalize_path = normalize_path;
|
||||
parse_forwarded = parse_forwarded;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue