* libs/core: Added garbage collector to luci.util.threadlocal to avoid memory leaks
* libs/http: Use env-Variables instead of headers for parse_message_body and subsequent functions * libs/http: Added missing urldecode call for parsing urlencoded params * libs/web: Ported luci.http to use ltn12 sources and sinks instead of sockets or file pointers * libs/sgi-cgi, libs/sgi-webuci, libs/sgi-wsapi: Updated to work with new luci.http.Request ABI
This commit is contained in:
parent
e2e9e119d6
commit
65870edf9f
6 changed files with 45 additions and 23 deletions
|
@ -281,6 +281,13 @@ function threadlocal()
|
||||||
rawset(self, thread, {})
|
rawset(self, thread, {})
|
||||||
end
|
end
|
||||||
rawget(self, thread)[key] = value
|
rawget(self, thread)[key] = value
|
||||||
|
|
||||||
|
-- Avoid memory leaks by removing abandoned stores
|
||||||
|
for k, v in pairs(self) do
|
||||||
|
if type(k) == "thread" and coroutine.status(k) == "dead" then
|
||||||
|
rawset(self, k, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
setmetatable(tbl, {__index = get, __newindex = set})
|
setmetatable(tbl, {__index = get, __newindex = set})
|
||||||
|
|
|
@ -378,8 +378,8 @@ process_states['urldecode-init'] = function( msg, chunk, filecb )
|
||||||
if chunk ~= nil then
|
if chunk ~= nil then
|
||||||
|
|
||||||
-- Check for Content-Length
|
-- Check for Content-Length
|
||||||
if msg.headers['Content-Length'] then
|
if msg.env.CONTENT_LENGTH then
|
||||||
msg.content_length = tonumber(msg.headers['Content-Length'])
|
msg.content_length = tonumber(msg.env.CONTENT_LENGTH)
|
||||||
|
|
||||||
if msg.content_length <= HTTP_MAX_CONTENT then
|
if msg.content_length <= HTTP_MAX_CONTENT then
|
||||||
-- Initialize buffer
|
-- Initialize buffer
|
||||||
|
@ -404,7 +404,6 @@ end
|
||||||
|
|
||||||
-- Process urldecoding stream, read and validate parameter key
|
-- Process urldecoding stream, read and validate parameter key
|
||||||
process_states['urldecode-key'] = function( msg, chunk, filecb )
|
process_states['urldecode-key'] = function( msg, chunk, filecb )
|
||||||
|
|
||||||
if chunk ~= nil then
|
if chunk ~= nil then
|
||||||
|
|
||||||
-- Prevent oversized requests
|
-- Prevent oversized requests
|
||||||
|
@ -436,6 +435,11 @@ process_states['urldecode-key'] = function( msg, chunk, filecb )
|
||||||
else
|
else
|
||||||
msg._urldeccallback = function( chunk, eof )
|
msg._urldeccallback = function( chunk, eof )
|
||||||
msg.params[key] = msg.params[key] .. chunk
|
msg.params[key] = msg.params[key] .. chunk
|
||||||
|
|
||||||
|
-- FIXME: Use a filter
|
||||||
|
if eof then
|
||||||
|
msg.params[key] = urldecode( msg.params[key] )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -520,9 +524,9 @@ end
|
||||||
function mimedecode_message_body( source, msg, filecb )
|
function mimedecode_message_body( source, msg, filecb )
|
||||||
|
|
||||||
-- Find mime boundary
|
-- Find mime boundary
|
||||||
if msg and msg.headers['Content-Type'] then
|
if msg and msg.env.CONTENT_TYPE then
|
||||||
|
|
||||||
local bound = msg.headers['Content-Type']:match("^multipart/form%-data; boundary=(.+)")
|
local bound = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)")
|
||||||
|
|
||||||
if bound then
|
if bound then
|
||||||
msg.mime_boundary = bound
|
msg.mime_boundary = bound
|
||||||
|
@ -666,7 +670,8 @@ function parse_message_header( source )
|
||||||
REQUEST_METHOD = msg.request_method:upper();
|
REQUEST_METHOD = msg.request_method:upper();
|
||||||
REQUEST_URI = msg.request_uri;
|
REQUEST_URI = msg.request_uri;
|
||||||
SCRIPT_NAME = msg.request_uri:gsub("?.+$","");
|
SCRIPT_NAME = msg.request_uri:gsub("?.+$","");
|
||||||
SCRIPT_FILENAME = "" -- XXX implement me
|
SCRIPT_FILENAME = ""; -- XXX implement me
|
||||||
|
SERVER_PROTOCOL = "HTTP/" .. msg.http_version
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Populate HTTP_* environment variables
|
-- Populate HTTP_* environment variables
|
||||||
|
@ -707,8 +712,8 @@ function parse_message_body( source, msg, filecb )
|
||||||
elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and
|
elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and
|
||||||
msg.env.CONTENT_TYPE == "application/x-www-form-urlencoded"
|
msg.env.CONTENT_TYPE == "application/x-www-form-urlencoded"
|
||||||
then
|
then
|
||||||
|
|
||||||
return urldecode_message_body( source, msg, filecb )
|
return urldecode_message_body( source, msg, filecb )
|
||||||
|
|
||||||
|
|
||||||
-- Unhandled encoding
|
-- Unhandled encoding
|
||||||
-- If a file callback is given then feed it line by line, else
|
-- If a file callback is given then feed it line by line, else
|
||||||
|
|
|
@ -24,12 +24,17 @@ limitations under the License.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
module("luci.sgi.cgi", package.seeall)
|
module("luci.sgi.cgi", package.seeall)
|
||||||
|
require("ltn12")
|
||||||
require("luci.http")
|
require("luci.http")
|
||||||
require("luci.sys")
|
require("luci.sys")
|
||||||
require("luci.dispatcher")
|
require("luci.dispatcher")
|
||||||
|
|
||||||
function run()
|
function run()
|
||||||
local r = luci.http.Request(luci.sys.getenv(), io.stdin, io.stderr)
|
local r = luci.http.Request(
|
||||||
|
luci.sys.getenv(),
|
||||||
|
ltn12.source.file(io.stdin),
|
||||||
|
ltn12.sink.file(io.stderr)
|
||||||
|
)
|
||||||
|
|
||||||
local x = coroutine.create(luci.dispatcher.httpdispatch)
|
local x = coroutine.create(luci.dispatcher.httpdispatch)
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,18 @@ limitations under the License.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
module("luci.sgi.webuci", package.seeall)
|
module("luci.sgi.webuci", package.seeall)
|
||||||
|
require("ltn12")
|
||||||
require("luci.http")
|
require("luci.http")
|
||||||
require("luci.util")
|
require("luci.util")
|
||||||
require("luci.dispatcher")
|
require("luci.dispatcher")
|
||||||
|
|
||||||
function run(env, vars)
|
function run(env, vars)
|
||||||
local r = luci.http.Request(env, {}, io.stderr)
|
local r = luci.http.Request(
|
||||||
|
env,
|
||||||
|
ltn12.source.empty(),
|
||||||
|
ltn12.sink.file(io.stderr)
|
||||||
|
)
|
||||||
|
|
||||||
r.message.params = vars
|
r.message.params = vars
|
||||||
|
|
||||||
local x = coroutine.create(luci.dispatcher.httpdispatch)
|
local x = coroutine.create(luci.dispatcher.httpdispatch)
|
||||||
|
|
|
@ -24,14 +24,17 @@ limitations under the License.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
module("luci.sgi.wsapi", package.seeall)
|
module("luci.sgi.wsapi", package.seeall)
|
||||||
|
require("ltn12")
|
||||||
require("luci.http")
|
require("luci.http")
|
||||||
require("luci.dispatcher")
|
require("luci.dispatcher")
|
||||||
require("luci.http.protocol")
|
require("luci.http.protocol")
|
||||||
|
|
||||||
function run(wsapi_env)
|
function run(wsapi_env)
|
||||||
local r = luci.http.Request(wsapi_env, wsapi_env.input, wsapi_env.error)
|
local r = luci.http.Request(
|
||||||
r.postds = function() return wsapi.request.parse_post_data(wsapi_env) end
|
wsapi_env,
|
||||||
r.getds = function() return wsapi.request.parse_qs(wsapi_env.QUERY_STRING) end
|
ltn12.source.file(wsapi_env.input),
|
||||||
|
ltn12.sink.file(wsapi_env.error)
|
||||||
|
)
|
||||||
|
|
||||||
local res, id, data1, data2 = true, 0, nil, nil
|
local res, id, data1, data2 = true, 0, nil, nil
|
||||||
local headers = {}
|
local headers = {}
|
||||||
|
|
|
@ -28,6 +28,7 @@ limitations under the License.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
module("luci.http", package.seeall)
|
module("luci.http", package.seeall)
|
||||||
|
require("ltn12")
|
||||||
require("luci.http.protocol")
|
require("luci.http.protocol")
|
||||||
require("luci.util")
|
require("luci.util")
|
||||||
|
|
||||||
|
@ -35,15 +36,10 @@ context = luci.util.threadlocal()
|
||||||
|
|
||||||
|
|
||||||
Request = luci.util.class()
|
Request = luci.util.class()
|
||||||
function Request.__init__(self, env, instream, errstream)
|
function Request.__init__(self, env, sourcein, sinkerr)
|
||||||
self.input = instream
|
self.input = sourcein
|
||||||
self.error = errstream
|
self.error = sinkerr
|
||||||
|
|
||||||
-- Provide readline function
|
|
||||||
self.inputreader = self.input.readline
|
|
||||||
or self.input.read and function() return self.input:read() end
|
|
||||||
or self.input.receive and function() return self.input:receive() end
|
|
||||||
or function() return nil end
|
|
||||||
|
|
||||||
-- File handler
|
-- File handler
|
||||||
self.filehandler = function() end
|
self.filehandler = function() end
|
||||||
|
@ -52,13 +48,13 @@ function Request.__init__(self, env, instream, errstream)
|
||||||
self.message = {
|
self.message = {
|
||||||
env = env,
|
env = env,
|
||||||
headers = {},
|
headers = {},
|
||||||
params = luci.http.protocol.urldecode_params("?"..(env.QUERY_STRING or "")),
|
params = luci.http.protocol.urldecode_params(env.QUERY_STRING or ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
setmetatable(self.message.params, {__index =
|
setmetatable(self.message.params, {__index =
|
||||||
function(tbl, key)
|
function(tbl, key)
|
||||||
luci.http.protocol.parse_message_body(
|
luci.http.protocol.parse_message_body(
|
||||||
self.inputreader,
|
self.input,
|
||||||
self.message,
|
self.message,
|
||||||
self.filehandler
|
self.filehandler
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue