mod_component_http/mod_component_http.lua
author Kim Alvefur <zash@zash.se>
Sat, 29 Apr 2023 13:09:46 +0200
changeset 5387 df11a2cbc7b7
parent 2999 032589c801d7
permissions -rw-r--r--
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange Likely to become mandatory in OAuth 2.1. Backwards compatible since the default 'plain' verifier would compare nil with nil if the relevant parameters are left out.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local http = require "net.http";
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local json = require "util.json";
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local st = require "util.stanza";
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
local xml = require "util.xml";
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
local unpack = rawget(_G, "unpack") or table.unpack;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
local url = module:get_option_string("component_post_url");
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
assert(url, "Missing required config option 'component_post_url'");
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
local stanza_kinds = module:get_option_set("post_stanza_types", { "message" });
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
local http_error_map = {
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
	[0]   = { "cancel", "remote-server-timeout", "Connection failure" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
	-- 4xx
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
	[400] = { "modify", "bad-request" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
	[401] = { "auth", "not-authorized" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	[402] = { "auth", "forbidden", "Payment required" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
	[403] = { "auth", "forbidden" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
	[404] = { "cancel", "item-not-found" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
	[410] = { "cancel", "gone" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
	-- 5xx
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
	[500] = { "cancel", "internal-server-error" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
	[501] = { "cancel", "feature-not-implemented" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
	[502] = { "cancel", "remote-server-timeout", "Bad gateway" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
	[503] = { "wait", "remote-server-timeout", "Service temporarily unavailable" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
	[504] = { "wait", "remote-server-timeout", "Gateway timeout" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
}
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
local function error_reply(stanza, code)
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
	local error = http_error_map[code] or { "cancel", "service-unavailable" };
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
	return st.error_reply(stanza, unpack(error, 1, 3));
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
function handle_stanza(event)
2962
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2956
diff changeset
    35
	local stanza = event.stanza;
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
	local request_body = json.encode({
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
		to = stanza.attr.to;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
		from = stanza.attr.from;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
		kind = stanza.name;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
		body = stanza.name == "message" and stanza:get_child_text("body") or nil;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
		stanza = tostring(stanza);
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
	});
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
	http.request(url, {
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
		body = request_body;
2999
032589c801d7 mod_component_http: Fix parameter order, see Prosody trunk e2919978673e for more info
Matthew Wild <mwild1@gmail.com>
parents: 2962
diff changeset
    45
	}, function (response_text, code, response)
2956
e8462d6dbc6d mod_component_http: Fix some [luacheck] warnings
Matthew Wild <mwild1@gmail.com>
parents: 2954
diff changeset
    46
		if stanza.attr.type == "error" then return; end -- Avoid error loops, don't reply to error stanzas
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
		if code == 200 and response_text and response.headers["content-type"] == "application/json" then
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
			local response_data = json.decode(response_text);
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
			if response_data.stanza then
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
				local reply_stanza = xml.parse(response_data.stanza);
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
				if reply_stanza then
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
					reply_stanza.attr.from, reply_stanza.attr.to = stanza.attr.to, stanza.attr.from;
2962
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2956
diff changeset
    53
					module:send(reply_stanza);
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
				else
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
					module:log("warn", "Unable to parse reply stanza");
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
				end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
			else
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
				local stanza_kind = response_data.kind or "message";
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
				local to = response_data.to or stanza.attr.from;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
				local from = response_data.from or stanza.attr.to;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
				local reply_stanza = st.stanza(stanza_kind, {
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
					to = to, from = from;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
					type = response_data.type or (stanza_kind == "message" and "chat") or nil;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
				});
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
				if stanza_kind == "message" and response_data.body then
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
					reply_stanza:tag("body"):text(tostring(response_data.body)):up();
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
				end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
				module:log("debug", "Sending %s", tostring(reply_stanza));
2962
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2956
diff changeset
    69
				module:send(reply_stanza);
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
			end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
		elseif code >= 200 and code <= 299 then
2962
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2956
diff changeset
    72
			return;
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
		else
2962
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2956
diff changeset
    74
			module:send(error_reply(stanza, code));
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
		end
2962
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2956
diff changeset
    76
		return true;
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    77
	end);
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
	return true;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
for stanza_kind in stanza_kinds do
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
	for _, jid_type in ipairs({ "host", "bare", "full" }) do
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    83
		module:hook(stanza_kind.."/"..jid_type, handle_stanza);
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    84
	end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    85
end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
-- Simple handler for an always-online JID that allows everyone to subscribe to presence
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
local function default_presence_handler(event)
2956
e8462d6dbc6d mod_component_http: Fix some [luacheck] warnings
Matthew Wild <mwild1@gmail.com>
parents: 2954
diff changeset
    89
	local stanza = event.stanza;
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    90
	module:log("debug", "Handling %s", tostring(stanza));
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    91
	if stanza.attr.type == "probe" then
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
		module:send(st.presence({ to = stanza.attr.from, from = stanza.attr.to.."/default" }));
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
	elseif stanza.attr.type == "subscribe" then
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
		module:send(st.presence({ type = "subscribed", to = stanza.attr.from, from = stanza.attr.to.."/default" }));
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    95
		module:send(st.presence({ to = stanza.attr.from, from = stanza.attr.to.."/default" }));
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
	elseif stanza.attr.type == "unsubscribe" then
2956
e8462d6dbc6d mod_component_http: Fix some [luacheck] warnings
Matthew Wild <mwild1@gmail.com>
parents: 2954
diff changeset
    97
		module:send(st.presence({ type = "unavailable", to = stanza.attr.from, from = stanza.attr.to.."/default" }));
2954
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    98
	end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    99
	return true;
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   100
end
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   101
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   102
module:hook("presence/bare", default_presence_handler, -1);