net/http/server.lua
changeset 11375 73f7acf8a61f
parent 11164 e9eeaefa09a7
child 11376 b877bd74d65e
equal deleted inserted replaced
11374:7c2ef5a1ec9c 11375:73f7acf8a61f
     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