Changeset

4715:4d6ebe54671e

Merge with backout
author Matthew Wild <mwild1@gmail.com>
date Thu, 26 Apr 2012 16:25:17 +0100
parents 4713:9c15fa5192d3 (diff) 4714:7dedf8cc173c (current diff)
children 4716:6eeb142a8073
files net/http/server.lua
diffstat 3 files changed, 100 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/net/http/parser.lua	Thu Apr 26 16:25:11 2012 +0100
+++ b/net/http/parser.lua	Thu Apr 26 16:25:17 2012 +0100
@@ -53,7 +53,6 @@
 							else
 								method, path, httpversion = line:match("^(%w+) (%S+) HTTP/(1%.[01])$");
 								if not method then error = true; return error_cb("invalid-status-line"); end
-								path = path:gsub("^//+", "/"); -- TODO parse url more
 							end
 						end
 					end
@@ -71,6 +70,12 @@
 							responseheaders = headers;
 						};
 					else
+						-- path normalization
+						if path:match("^https?://") then
+							headers.host, path = path:match("^https?://([^/]*)(.*)");
+						end
+						path = path:gsub("^//+", "/"); -- TODO parse url more
+
 						len = len or 0;
 						packet = {
 							method = method;
--- a/net/http/server.lua	Thu Apr 26 16:25:11 2012 +0100
+++ b/net/http/server.lua	Thu Apr 26 16:25:17 2012 +0100
@@ -75,7 +75,12 @@
 local handle_request;
 local _1, _2, _3;
 local function _handle_request() return handle_request(_1, _2, _3); end
-local function _traceback_handler(err) log("error", "Traceback[http]: %s: %s", tostring(err), debug.traceback()); end
+
+local last_err;
+local function _traceback_handler(err) last_err = err; log("error", "Traceback[http]: %s: %s", tostring(err), debug.traceback()); end
+events.add_handler("http-error", function (error)
+	return "Error processing request: "..codes[error.code]..". Check your error log for more information.";
+end, -1);
 
 function listener.onconnect(conn)
 	local secure = conn:ssl() and true or nil;
@@ -90,7 +95,7 @@
 			--handle_request(conn, request, process_next);
 			_1, _2, _3 = conn, request, process_next;
 			if not xpcall(_handle_request, _traceback_handler) then
-				conn:write("HTTP/1.0 503 Internal Server Error\r\n\r\nAn error occured during the processing of this request.");
+				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
 		else
@@ -161,10 +166,17 @@
 	};
 	conn._http_open_response = response;
 
+	local err;
 	if not request.headers.host then
+		err = "No 'Host' header";
+	elseif not request.path then
+		err = "Invalid path";
+	end
+	
+	if err then
 		response.status_code = 400;
 		response.headers.content_type = "text/html";
-		response:send("<html><head>400 Bad Request</head><body>400 Bad Request: No Host header.</body></html>");
+		response:send(events.fire_event("http-error", { code = 400, message = err }));
 	else
 		local host = request.headers.host;
 		if host then
@@ -179,6 +191,9 @@
 					local result_type = type(result);
 					if result_type == "number" then
 						response.status_code = result;
+						if result >= 400 then
+							body = events.fire_event("http-error", { code = result });
+						end
 					elseif result_type == "string" then
 						body = result;
 					elseif result_type == "table" then
@@ -197,7 +212,7 @@
 		-- if handler not called, return 404
 		response.status_code = 404;
 		response.headers.content_type = "text/html";
-		response:send("<html><head><title>404 Not Found</title></head><body>404 Not Found: No such page.</body></html>");
+		response:send(events.fire_event("http-error", { code = 404 }));
 	end
 end
 function _M.send_response(response, body)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/mod_http_errors.lua	Thu Apr 26 16:25:17 2012 +0100
@@ -0,0 +1,75 @@
+module:set_global();
+module:depends("http");
+
+local server = require "net.http.server";
+local codes = require "net.http.codes";
+local termcolours = require "util.termcolours";
+
+local show_private = module:get_option_boolean("http_errors_detailed", false);
+
+local default_messages = {
+	[400] = { "What kind of request do you call that??" };
+	[403] = { "You're not allowed to do that." };
+	[404] = { "Whatever you were looking for is not here. %";
+		"Where did you put it?", "It's behind you.", "Keep looking." };
+	[500] = { "% Check your error log for more info.";
+		"Gremlins.", "It broke.", "Don't look at me." };
+};
+
+local messages = setmetatable(module:get_option("http_errors_messages", {}), { __index = default_messages });
+
+local html = [[
+<!DOCTYPE html>
+<html>
+<head>
+	<meta charset="utf-8">
+	<style>
+		body{
+			margin-top:14%;
+			text-align:center;
+			background-color:#F8F8F8;
+			font-family:sans-serif;
+		}
+		h1{
+			font-size:xx-large;
+		}
+		p{
+			font-size:x-large;
+		}
+		p+p { font-size: large; font-family: courier }
+        </style>
+</head>
+<body>
+        <h1>$title</h1>
+        <p>$message</p>
+        <p>$extra</p>
+</body>
+</html>]];
+html = html:gsub("%s%s+", "");
+
+local entities = {
+	["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;",
+	["'"] = "&apos;", ["\""] = "&quot;", ["\n"] = "<br/>",
+};
+
+local function tohtml(plain)
+	return (plain:gsub("[<>&'\"\n]", entities));
+	
+end
+
+local function get_page(code, extra)
+	local message = messages[code];
+	if message then
+		return (html:gsub("$(%a+)", {
+			title = rawget(codes, code) or ("Code "..tostring(code));
+			message = message[1]:gsub("%%", function ()
+				return message[math.random(2, math.max(#message,2))];
+			end);
+			extra = tohtml(extra or "");
+		}));
+	end
+end
+
+module:hook_object_event(server, "http-error", function (event)
+	return get_page(event.code, (show_private and event.private_message) or event.message);
+end);