diff plugins/mod_http_errors.lua @ 13959:1b95d50cfa18

mod_http_errors: Return errors as JSON if requester prefers that
author Matthew Wild <mwild1@gmail.com>
date Fri, 26 Sep 2025 12:43:38 +0100
parents f72ca74de456
children 36d361722889
line wrap: on
line diff
--- a/plugins/mod_http_errors.lua	Fri Sep 26 12:06:14 2025 +0100
+++ b/plugins/mod_http_errors.lua	Fri Sep 26 12:43:38 2025 +0100
@@ -2,9 +2,13 @@
 
 local server = require "prosody.net.http.server";
 local codes = require "prosody.net.http.codes";
+local http_errors = require "prosody.net.http.errors".registry;
+local json = require "prosody.util.json";
+local new_short_id = require "prosody.util.id".short;
 local xml_escape = require "prosody.util.stanza".xml_escape;
 local render = require "prosody.util.interpolation".new("%b{}", xml_escape);
 
+
 local show_private = module:get_option_boolean("http_errors_detailed", false);
 local always_serve = module:get_option_boolean("http_errors_always_show", true);
 local default_message = { module:get_option_string("http_errors_default_message", "That's all I know.") };
@@ -77,6 +81,27 @@
 	return get_page(event.code, (show_private and event.private_message) or event.message or (event.error and event.error.text));
 end);
 
+-- Return error object as JSON if that's what requester prefers
+module:hook_object_event(server, "http-error", function (event)
+	if event.request.headers.accept:match("^application/json") then
+		event.response.headers.content_type = "application/json";
+		local error = event.request and event.error;
+		if not error then
+			error = http_errors[event.response.status_code];
+		end
+		local extra = error.extra;
+		return json.encode({
+			instance_id = error.instance_id or new_short_id();
+			type = error.type;
+			condition = error.condition;
+			text = error.text or (show_private and event.private_message) or event.message;
+			namespace = extra and extra.namespace;
+			subcondition = extra and extra.condition;
+			source = error.source or "mod_http_errors";
+		});
+	end
+end, 0.1);
+
 -- Way to use the template for other things so to give a consistent appearance
 module:hook("http-message", function (event)
 	if event.response then