diff options
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Read the auth cookie in linear time
Splitting the header with patterns that backtrack over spaces cost a quarter of a second per request at the 8 KB line most web servers allow, and a second at 16 KB, without any login. auth-file's trim had the same shape and now reads the cookie as well.
Diffstat (limited to 'custom/extensions/auth-inline.lua')
-rw-r--r--custom/extensions/auth-inline.lua26
1 file changed, 21 insertions, 5 deletions
diff --git a/custom/extensions/auth-inline.lua b/custom/extensions/auth-inline.lua
index 5363a38..de91f88 100644
--- a/custom/extensions/auth-inline.lua
+++ b/custom/extensions/auth-inline.lua
@@ -168,16 +168,32 @@ function parse_query(query)
return params
end
-local function pattern_escape(s)
- return (string.gsub(s, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1"))
+-- Lua patterns backtrack, so "^%s*(.-)%s*$" costs the square of a run of
+-- spaces inside the text. Finding each end directly stays linear, which
+-- matters for the Cookie header a visitor writes.
+local function trim(text)
+ local first = text:find("%S")
+ if first == nil then
+ return ""
+ end
+ local last = #text
+ while text:find("^%s", last) do
+ last = last - 1
+ end
+ return text:sub(first, last)
end
-- The token comes back still URL encoded by secure_value. Decoding it here
-- would break the signature check for any value carrying a percent escape.
--- The name is escaped because it lands in a Lua pattern.
function get_cookie(cookies, name)
- cookies = string.gsub(";" .. (cookies or "") .. ";", "%s*;%s*", ";")
- return string.match(cookies, ";" .. pattern_escape(name) .. "=(.-);")
+ for raw in string.gmatch(cookies or "", "[^;]+") do
+ local pair = trim(raw)
+ local equals = pair:find("=", 1, true)
+ if equals and pair:sub(1, equals - 1) == name then
+ return pair:sub(equals + 1)
+ end
+ end
+ return nil
end
function tohex(bytes)