author | Matthew Wild <mwild1@gmail.com> |
Wed, 04 Apr 2018 21:59:00 +0100 | |
changeset 2999 | 032589c801d7 |
parent 2962 | 13acce68a89c |
permissions | -rw-r--r-- |
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); |