aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2020-07-12 20:31:31 +0200
committerKim Alvefur <zash@zash.se>2020-07-12 20:31:31 +0200
commitf0202d38c226c5e1657dc48319ae5f1dd81c1c2b (patch)
tree351e94ce0d0f7c475a15366d20734ec8737d81ed /net
parentcb489d06e1c0e5764269d96388a4f9504676bd09 (diff)
downloadprosody-f0202d38c226c5e1657dc48319ae5f1dd81c1c2b.tar.gz
prosody-f0202d38c226c5e1657dc48319ae5f1dd81c1c2b.zip
net.http.server: Enable async during HTTP request handling (fixes #1487)
Diffstat (limited to 'net')
-rw-r--r--net/http/server.lua51
1 files changed, 23 insertions, 28 deletions
diff --git a/net/http/server.lua b/net/http/server.lua
index 75859719..c35ee670 100644
--- a/net/http/server.lua
+++ b/net/http/server.lua
@@ -1,5 +1,5 @@
-local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat;
+local t_insert, t_concat = table.insert, table.concat;
local parser_new = require "net.http.parser".new;
local events = require "util.events".new();
local addserver = require "net.server".addserver;
@@ -8,14 +8,12 @@ local os_date = os.date;
local pairs = pairs;
local s_upper = string.upper;
local setmetatable = setmetatable;
-local xpcall = require "util.xpcall".xpcall;
-local traceback = debug.traceback;
-local tostring = tostring;
local cache = require "util.cache";
local codes = require "net.http.codes";
local promise = require "util.promise";
local errors = require "util.error";
local blocksize = 2^16;
+local async = require "util.async";
local _M = {};
@@ -91,39 +89,36 @@ setmetatable(events._handlers, {
local handle_request;
-local last_err;
-local function _traceback_handler(err) last_err = err; log("error", "Traceback[httpserver]: %s", traceback(tostring(err), 2)); end
events.add_handler("http-error", function (error)
return "Error processing request: "..codes[error.code]..". Check your error log for more information.";
end, -1);
+local runner_callbacks = {};
+
+function runner_callbacks:ready()
+ self.data:resume();
+end
+
+function runner_callbacks:waiting()
+ self.data:pause();
+end
+
+function runner_callbacks:error(err)
+ log("error", "Traceback[httpserver]: %s", err);
+ self.data:write("HTTP/1.0 500 Internal Server Error\r\n\r\n"..events.fire_event("http-error", { code = 500, private_message = err }));
+ self.data:close();
+end
+
function listener.onconnect(conn)
local secure = conn:ssl() and true or nil;
- local pending = {};
- local waiting = false;
- local function process_next()
- if waiting then return; end -- log("debug", "can't process_next, waiting");
- waiting = true;
- while sessions[conn] and #pending > 0 do
- local request = t_remove(pending);
- --log("debug", "process_next: %s", request.path);
- if not xpcall(handle_request, _traceback_handler, conn, request, process_next) then
- conn:write("HTTP/1.0 500 Internal Server Error\r\n\r\n"..events.fire_event("http-error", { code = 500, private_message = last_err }));
- conn:close();
- end
- end
- --log("debug", "ready for more");
- waiting = false;
- end
+ conn._thread = async.runner(function (request)
+ local wait, done = async.waiter();
+ handle_request(conn, request, done); wait();
+ end, runner_callbacks, conn);
local function success_cb(request)
--log("debug", "success_cb: %s", request.path);
- if waiting then
- log("error", "http connection handler is not reentrant: %s", request.path);
- assert(false, "http connection handler is not reentrant");
- end
request.secure = secure;
- t_insert(pending, request);
- process_next();
+ conn._thread:run(request);
end
local function error_cb(err)
log("debug", "error_cb: %s", err or "<nil>");