Software /
code /
prosody-modules
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 |
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); |