1 |
1 |
2 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; |
2 local t_insert, t_concat = table.insert, table.concat; |
3 local parser_new = require "net.http.parser".new; |
3 local parser_new = require "net.http.parser".new; |
4 local events = require "util.events".new(); |
4 local events = require "util.events".new(); |
5 local addserver = require "net.server".addserver; |
5 local addserver = require "net.server".addserver; |
6 local log = require "util.logger".init("http.server"); |
6 local log = require "util.logger".init("http.server"); |
7 local os_date = os.date; |
7 local os_date = os.date; |
8 local pairs = pairs; |
8 local pairs = pairs; |
9 local s_upper = string.upper; |
9 local s_upper = string.upper; |
10 local setmetatable = setmetatable; |
10 local setmetatable = setmetatable; |
11 local xpcall = require "util.xpcall".xpcall; |
|
12 local traceback = debug.traceback; |
|
13 local tostring = tostring; |
|
14 local cache = require "util.cache"; |
11 local cache = require "util.cache"; |
15 local codes = require "net.http.codes"; |
12 local codes = require "net.http.codes"; |
16 local promise = require "util.promise"; |
13 local promise = require "util.promise"; |
17 local errors = require "util.error"; |
14 local errors = require "util.error"; |
18 local blocksize = 2^16; |
15 local blocksize = 2^16; |
|
16 local async = require "util.async"; |
19 |
17 |
20 local _M = {}; |
18 local _M = {}; |
21 |
19 |
22 local sessions = {}; |
20 local sessions = {}; |
23 local incomplete = {}; |
21 local incomplete = {}; |
89 end; |
87 end; |
90 }); |
88 }); |
91 |
89 |
92 local handle_request; |
90 local handle_request; |
93 |
91 |
94 local last_err; |
|
95 local function _traceback_handler(err) last_err = err; log("error", "Traceback[httpserver]: %s", traceback(tostring(err), 2)); end |
|
96 events.add_handler("http-error", function (error) |
92 events.add_handler("http-error", function (error) |
97 return "Error processing request: "..codes[error.code]..". Check your error log for more information."; |
93 return "Error processing request: "..codes[error.code]..". Check your error log for more information."; |
98 end, -1); |
94 end, -1); |
99 |
95 |
|
96 local runner_callbacks = {}; |
|
97 |
|
98 function runner_callbacks:ready() |
|
99 self.data:resume(); |
|
100 end |
|
101 |
|
102 function runner_callbacks:waiting() |
|
103 self.data:pause(); |
|
104 end |
|
105 |
|
106 function runner_callbacks:error(err) |
|
107 log("error", "Traceback[httpserver]: %s", err); |
|
108 self.data:write("HTTP/1.0 500 Internal Server Error\r\n\r\n"..events.fire_event("http-error", { code = 500, private_message = err })); |
|
109 self.data:close(); |
|
110 end |
|
111 |
100 function listener.onconnect(conn) |
112 function listener.onconnect(conn) |
101 local secure = conn:ssl() and true or nil; |
113 local secure = conn:ssl() and true or nil; |
102 local pending = {}; |
114 conn._thread = async.runner(function (request) |
103 local waiting = false; |
115 local wait, done = async.waiter(); |
104 local function process_next() |
116 handle_request(conn, request, done); wait(); |
105 if waiting then return; end -- log("debug", "can't process_next, waiting"); |
117 end, runner_callbacks, conn); |
106 waiting = true; |
|
107 while sessions[conn] and #pending > 0 do |
|
108 local request = t_remove(pending); |
|
109 --log("debug", "process_next: %s", request.path); |
|
110 if not xpcall(handle_request, _traceback_handler, conn, request, process_next) then |
|
111 conn:write("HTTP/1.0 500 Internal Server Error\r\n\r\n"..events.fire_event("http-error", { code = 500, private_message = last_err })); |
|
112 conn:close(); |
|
113 end |
|
114 end |
|
115 --log("debug", "ready for more"); |
|
116 waiting = false; |
|
117 end |
|
118 local function success_cb(request) |
118 local function success_cb(request) |
119 --log("debug", "success_cb: %s", request.path); |
119 --log("debug", "success_cb: %s", request.path); |
120 if waiting then |
|
121 log("error", "http connection handler is not reentrant: %s", request.path); |
|
122 assert(false, "http connection handler is not reentrant"); |
|
123 end |
|
124 request.secure = secure; |
120 request.secure = secure; |
125 t_insert(pending, request); |
121 conn._thread:run(request); |
126 process_next(); |
|
127 end |
122 end |
128 local function error_cb(err) |
123 local function error_cb(err) |
129 log("debug", "error_cb: %s", err or "<nil>"); |
124 log("debug", "error_cb: %s", err or "<nil>"); |
130 -- FIXME don't close immediately, wait until we process current stuff |
125 -- FIXME don't close immediately, wait until we process current stuff |
131 -- FIXME if err, send off a bad-request response |
126 -- FIXME if err, send off a bad-request response |