luci-base: refactor luci.http

- Rewrite getcookie() to use liblucihttp header value parsing
 - Rewrite setfilehandler() to use local variables and have cleaner code
 - Fix build_querystring() to actually *en*code the given params

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2018-04-18 14:05:41 +02:00
parent db0d5b33d0
commit 8f66de12c1

View file

@ -7,6 +7,7 @@ local util = require "luci.util"
local string = require "string" local string = require "string"
local coroutine = require "coroutine" local coroutine = require "coroutine"
local table = require "table" local table = require "table"
local lhttp = require "lucihttp"
local ipairs, pairs, next, type, tostring, error = local ipairs, pairs, next, type, tostring, error =
ipairs, pairs, next, type, tostring, error ipairs, pairs, next, type, tostring, error
@ -73,10 +74,7 @@ function Request.content(self)
end end
function Request.getcookie(self, name) function Request.getcookie(self, name)
local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";") return lhttp.header_attribute("cookie; " .. (self:getenv("HTTP_COOKIE") or ""), name)
local p = ";" .. name .. "=(.-);"
local i, j, value = c:find(p)
return value and urldecode(value)
end end
function Request.getenv(self, name) function Request.getenv(self, name)
@ -90,34 +88,28 @@ end
function Request.setfilehandler(self, callback) function Request.setfilehandler(self, callback)
self.filehandler = callback self.filehandler = callback
-- If input has already been parsed then any files are either in temporary files if not self.parsed_input then
-- or are in self.message.params[key] return
if self.parsed_input then end
for param, value in pairs(self.message.params) do
repeat -- If input has already been parsed then uploads are stored as unlinked
-- We're only interested in files -- temporary files pointed to by open file handles in the parameter
if (not value["file"]) then break end -- value table. Loop all params, and invoke the file callback for any
-- If we were able to write to temporary file -- param with an open file handle.
if (value["fd"]) then local name, value
fd = value["fd"] for name, value in pairs(self.message.params) do
local eof = false if type(value) == "table" then
repeat while value.fd do
filedata = fd:read(1024) local data = value.fd:read(1024)
if (filedata:len() < 1024) then local eof = (not data or data == "")
eof = true
end callback(value, data, eof)
callback({ name=value["name"], file=value["file"] }, filedata, eof)
until (eof) if eof then
fd:close() value.fd:close()
value["fd"] = nil value.fd = nil
-- We had to read into memory
else
-- There should only be one numbered value in table - the data
for k, v in ipairs(value) do
callback({ name=value["name"], file=value["file"] }, v, true)
end end
end end
until true
end end
end end
end end
@ -254,14 +246,14 @@ function redirect(url)
end end
function build_querystring(q) function build_querystring(q)
local s = { "?" } local s, n, k, v = {}, 1, nil, nil
for k, v in pairs(q) do for k, v in pairs(q) do
if #s > 1 then s[#s+1] = "&" end s[n+0] = (n == 1) and "?" or "&"
s[n+1] = util.urlencode(k)
s[#s+1] = urldecode(k) s[n+2] = "="
s[#s+1] = "=" s[n+3] = util.urlencode(v)
s[#s+1] = urldecode(v) n = n + 4
end end
return table.concat(s, "") return table.concat(s, "")