plugins/mod_http_errors.lua
author Kim Alvefur <zash@zash.se>
Sun, 24 Mar 2024 21:32:00 +0100
changeset 13468 2dbc169aae6a
parent 13397 f72ca74de456
permissions -rw-r--r--
util.startup: Abort before initialization of logging when started as root Prevents creation of log files owned by the root user which could be inaccessible once started correctly.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
module:set_global();
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11824
diff changeset
     3
local server = require "prosody.net.http.server";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11824
diff changeset
     4
local codes = require "prosody.net.http.codes";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11824
diff changeset
     5
local xml_escape = require "prosody.util.stanza".xml_escape;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11824
diff changeset
     6
local render = require "prosody.util.interpolation".new("%b{}", xml_escape);
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
local show_private = module:get_option_boolean("http_errors_detailed", false);
4737
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
     9
local always_serve = module:get_option_boolean("http_errors_always_show", true);
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
    10
local default_message = { module:get_option_string("http_errors_default_message", "That's all I know.") };
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
local default_messages = {
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
	[400] = { "What kind of request do you call that??" };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
	[403] = { "You're not allowed to do that." };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
	[404] = { "Whatever you were looking for is not here. %";
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
		"Where did you put it?", "It's behind you.", "Keep looking." };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
	[500] = { "% Check your error log for more info.";
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
		"Gremlins.", "It broke.", "Don't look at me." };
11407
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    18
	["/"] = {
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    19
		"A study in simplicity.";
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    20
		"Better catch it!";
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    21
		"Don't just stand there, go after it!";
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    22
		"Well, say something, before it runs too far!";
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    23
		"Welcome to the world of XMPP!";
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    24
		"You can do anything in XMPP!"; -- "The only limit is XML.";
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    25
		"You can do anything with Prosody!"; -- the only limit is memory?
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
    26
	};
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
};
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
local messages = setmetatable(module:get_option("http_errors_messages", {}), { __index = default_messages });
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
local html = [[
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
<!DOCTYPE html>
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
<html>
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
<head>
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    35
<meta charset="utf-8">
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    36
<title>{title}</title>
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    37
<style>
13397
f72ca74de456 mod_http_errors: Simplify CSS via built-in dark mode
Kim Alvefur <zash@zash.se>
parents: 12981
diff changeset
    38
:root{color-scheme:light dark}
f72ca74de456 mod_http_errors: Simplify CSS via built-in dark mode
Kim Alvefur <zash@zash.se>
parents: 12981
diff changeset
    39
body{margin-top:14%;text-align:center;font-family:sans-serif}
11392
60a61c509d87 mod_http_errors: Minify CSS
Kim Alvefur <zash@zash.se>
parents: 11159
diff changeset
    40
h1{font-size:xx-large}
60a61c509d87 mod_http_errors: Minify CSS
Kim Alvefur <zash@zash.se>
parents: 11159
diff changeset
    41
p{font-size:x-large}
11399
d336b28b4002 mod_http_errors: Style tweak
Kim Alvefur <zash@zash.se>
parents: 11394
diff changeset
    42
p.warning>span{font-size:large;background-color:yellow}
11392
60a61c509d87 mod_http_errors: Minify CSS
Kim Alvefur <zash@zash.se>
parents: 11159
diff changeset
    43
p.extra{font-size:large;font-family:courier}
60a61c509d87 mod_http_errors: Minify CSS
Kim Alvefur <zash@zash.se>
parents: 11159
diff changeset
    44
@media(prefers-color-scheme:dark){
11399
d336b28b4002 mod_http_errors: Style tweak
Kim Alvefur <zash@zash.se>
parents: 11394
diff changeset
    45
p.warning>span{background-color:inherit;color:yellow}
11158
dd81a318a794 mod_http_errors: Dark theme!
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
    46
}
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    47
</style>
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
</head>
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
<body>
11666
a8798e04b5c8 mod_http_errors: Allow adding icons on error pages
Kim Alvefur <zash@zash.se>
parents: 11408
diff changeset
    50
<h1>{icon?{icon_raw!?}} {title}</h1>
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    51
<p>{message}</p>
11399
d336b28b4002 mod_http_errors: Style tweak
Kim Alvefur <zash@zash.se>
parents: 11394
diff changeset
    52
{warning&<p class="warning"><span>&#9888; {warning?} &#9888;</span></p>}
11159
8d692a8a8f48 mod_http_errors: Remove 'extra' element when empty
Kim Alvefur <zash@zash.se>
parents: 11158
diff changeset
    53
{extra&<p class="extra">{extra?}</p>}
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
</body>
7495
9a749cf8c1ba mod_http_errors: Add a newline after end of HTML
Kim Alvefur <zash@zash.se>
parents: 5776
diff changeset
    55
</html>
9a749cf8c1ba mod_http_errors: Add a newline after end of HTML
Kim Alvefur <zash@zash.se>
parents: 5776
diff changeset
    56
]];
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
local function get_page(code, extra)
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
	local message = messages[code];
4737
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
    60
	if always_serve or message then
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
    61
		message = message or default_message;
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    62
		return render(html, {
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
			title = rawget(codes, code) or ("Code "..tostring(code));
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
			message = message[1]:gsub("%%", function ()
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
				return message[math.random(2, math.max(#message,2))];
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
			end);
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    67
			extra = extra;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    68
		});
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
	end
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
end
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
11408
f7704f987439 mod_http_errors: Add some comments
Kim Alvefur <zash@zash.se>
parents: 11407
diff changeset
    72
-- Main error page handler
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
module:hook_object_event(server, "http-error", function (event)
8366
e2460edc2a2f mod_http_errors: Set Content-Type header to HTML (fixes #1030)
Kim Alvefur <zash@zash.se>
parents: 7495
diff changeset
    74
	if event.response then
e2460edc2a2f mod_http_errors: Set Content-Type header to HTML (fixes #1030)
Kim Alvefur <zash@zash.se>
parents: 7495
diff changeset
    75
		event.response.headers.content_type = "text/html; charset=utf-8";
e2460edc2a2f mod_http_errors: Set Content-Type header to HTML (fixes #1030)
Kim Alvefur <zash@zash.se>
parents: 7495
diff changeset
    76
	end
10578
f70c874b7936 mod_http_errors: Use text from util.errror object if included
Kim Alvefur <zash@zash.se>
parents: 10434
diff changeset
    77
	return get_page(event.code, (show_private and event.private_message) or event.message or (event.error and event.error.text));
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
end);
10434
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
    79
11408
f7704f987439 mod_http_errors: Add some comments
Kim Alvefur <zash@zash.se>
parents: 11407
diff changeset
    80
-- Way to use the template for other things so to give a consistent appearance
11393
29e7ed75ed3f mod_http_errors: Add way to reuse the error page template
Kim Alvefur <zash@zash.se>
parents: 11392
diff changeset
    81
module:hook("http-message", function (event)
29e7ed75ed3f mod_http_errors: Add way to reuse the error page template
Kim Alvefur <zash@zash.se>
parents: 11392
diff changeset
    82
	if event.response then
29e7ed75ed3f mod_http_errors: Add way to reuse the error page template
Kim Alvefur <zash@zash.se>
parents: 11392
diff changeset
    83
		event.response.headers.content_type = "text/html; charset=utf-8";
29e7ed75ed3f mod_http_errors: Add way to reuse the error page template
Kim Alvefur <zash@zash.se>
parents: 11392
diff changeset
    84
	end
29e7ed75ed3f mod_http_errors: Add way to reuse the error page template
Kim Alvefur <zash@zash.se>
parents: 11392
diff changeset
    85
	return render(html, event);
11824
0375ef78ed64 mod_http_errors: Make it easier to override 'http-message' handler
Kim Alvefur <zash@zash.se>
parents: 11668
diff changeset
    86
end, -1);
11393
29e7ed75ed3f mod_http_errors: Add way to reuse the error page template
Kim Alvefur <zash@zash.se>
parents: 11392
diff changeset
    87
11667
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    88
local icon = [[
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    89
<svg xmlns="http://www.w3.org/2000/svg" height="0.7em" viewBox="0 0 480 480" width="0.7em">
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    90
<rect fill="#6197df" height="220" rx="60" ry="60" width="220" x="10" y="10"></rect>
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    91
<rect fill="#f29b00" height="220" rx="60" ry="60" width="220" x="10" y="240"></rect>
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    92
<rect fill="#f29b00" height="220" rx="60" ry="60" width="220" x="240" y="10"></rect>
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    93
<rect fill="#6197df" height="220" rx="60" ry="60" width="220" x="240" y="240"></rect>
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    94
</svg>
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    95
]];
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
    96
11408
f7704f987439 mod_http_errors: Add some comments
Kim Alvefur <zash@zash.se>
parents: 11407
diff changeset
    97
-- Something nicer shown instead of 404 at the root path, if nothing else handles this path
10434
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
    98
module:hook_object_event(server, "http-error", function (event)
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
    99
	local request, response = event.request, event.response;
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   100
	if request and response and request.path == "/" and response.status_code == 404 then
11668
d83f8f44caea mod_http_errors: Set status code 200 from root page
Kim Alvefur <zash@zash.se>
parents: 11667
diff changeset
   101
		response.status_code = 200;
10434
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   102
		response.headers.content_type = "text/html; charset=utf-8";
11407
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
   103
		local message = messages["/"];
10434
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   104
		return render(html, {
11667
04fa947784bc mod_http_errors: Add a Prosody logo to root page
Kim Alvefur <zash@zash.se>
parents: 11666
diff changeset
   105
				icon_raw = icon,
10434
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   106
				title = "Prosody is running!";
11407
747e8245f180 mod_http_errors: Add some silly variations for the '/' page
Kim Alvefur <zash@zash.se>
parents: 11399
diff changeset
   107
				message = message[math.random(#message)];
10434
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   108
			});
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   109
	end
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   110
end, 1);
46dd9df2db0c mod_http_errors: Show a friendly page instead of 404 on top level
Kim Alvefur <zash@zash.se>
parents: 9764
diff changeset
   111