Annotate

mod_component_http/mod_component_http.lua @ 5119:048e339706ba

mod_rest: Remove manual reference expansion in schema This hack was originally added to reduce the number of definitions of common attributes (type, to, from etc) and payloads (e.g. delay). This predated pointers and references, and until now was needed because parsing picked out the correct stanza kind from the schema, which broke internal references. Removing this hack paves the way for allowing the schema to be configured or customized more easily.
author Kim Alvefur <zash@zash.se>
date Tue, 20 Dec 2022 21:48:28 +0100
parent 2995:032589c801d7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2950
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)
2958
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2952
diff changeset
35 local stanza = event.stanza;
2950
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;
2995
032589c801d7 mod_component_http: Fix parameter order, see Prosody trunk e2919978673e for more info
Matthew Wild <mwild1@gmail.com>
parents: 2958
diff changeset
45 }, function (response_text, code, response)
2952
e8462d6dbc6d mod_component_http: Fix some [luacheck] warnings
Matthew Wild <mwild1@gmail.com>
parents: 2950
diff changeset
46 if stanza.attr.type == "error" then return; end -- Avoid error loops, don't reply to error stanzas
2950
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;
2958
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2952
diff changeset
53 module:send(reply_stanza);
2950
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));
2958
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2952
diff changeset
69 module:send(reply_stanza);
2950
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
2958
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2952
diff changeset
72 return;
2950
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 else
2958
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2952
diff changeset
74 module:send(error_reply(stanza, code));
2950
18e6d437003f mod_component_http: Allow implementing a component over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 end
2958
13acce68a89c mod_component_http: Fix to use module:send() instead of origin.send() (thanks Wiktor)
Matthew Wild <mwild1@gmail.com>
parents: 2952
diff changeset
76 return true;
2950
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)
2952
e8462d6dbc6d mod_component_http: Fix some [luacheck] warnings
Matthew Wild <mwild1@gmail.com>
parents: 2950
diff changeset
89 local stanza = event.stanza;
2950
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
2952
e8462d6dbc6d mod_component_http: Fix some [luacheck] warnings
Matthew Wild <mwild1@gmail.com>
parents: 2950
diff changeset
97 module:send(st.presence({ type = "unavailable", to = stanza.attr.from, from = stanza.attr.to.."/default" }));
2950
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);