Mercurial > prosody-modules
annotate mod_rest/mod_rest.lua @ 3866:c0df50ce96f0
mod_rest: Handle internal http request errors early and then return
Skips over attempted parsing of the payload which usually failed since
the body is an error string like "connection refused", so this produced
useless errors.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 25 Jan 2020 20:22:12 +0100 |
parents | a44e20cbd986 |
children | 839224be5299 |
rev | line source |
---|---|
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
1 -- RESTful API |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
2 -- |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
3 -- Copyright (c) 2019-2020 Kim Alvefur |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
4 -- |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
5 -- This file is MIT/X11 licensed. |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
6 |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
7 local errors = require "util.error"; |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
8 local http = require "net.http"; |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
9 local id = require "util.id"; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
10 local jid = require "util.jid"; |
3813 | 11 local json = require "util.json"; |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
12 local st = require "util.stanza"; |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
13 local xml = require "util.xml"; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
14 |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
15 local allow_any_source = module:get_host_type() == "component"; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
16 local validate_from_addresses = module:get_option_boolean("validate_from_addresses", true); |
3802
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
17 local secret = assert(module:get_option_string("rest_credentials"), "rest_credentials is a required setting"); |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
18 local auth_type = assert(secret:match("^%S+"), "Format of rest_credentials MUST be like 'Bearer secret'"); |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
19 assert(auth_type == "Bearer", "Only 'Bearer' is supported in rest_credentials"); |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
20 |
3813 | 21 local jsonmap = module:require"jsonmap"; |
3802
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
22 -- Bearer token |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
23 local function check_credentials(request) |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
24 return request.headers.authorization == secret; |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
25 end |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
26 |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
27 local function parse(mimetype, data) |
3825
802087d3155a
mod_rest: Fix traceback on missing content-type header
Kim Alvefur <zash@zash.se>
parents:
3824
diff
changeset
|
28 mimetype = mimetype and mimetype:match("^[^; ]*"); |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
29 if mimetype == "application/xmpp+xml" then |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
30 return xml.parse(data); |
3813 | 31 elseif mimetype == "application/json" then |
32 local parsed, err = json.decode(data); | |
33 if not parsed then | |
34 return parsed, err; | |
35 end | |
36 return jsonmap.json2st(parsed); | |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
37 elseif mimetype == "text/plain" then |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
38 return st.message({ type = "chat" }, data); |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
39 end |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
40 return nil, "unknown-payload-type"; |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
41 end |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
42 |
3813 | 43 local supported_types = { "application/xmpp+xml", "application/json" }; |
44 | |
45 local function decide_type(accept) | |
46 -- assumes the accept header is sorted | |
47 local ret = supported_types[1]; | |
48 for i = 2, #supported_types do | |
49 if (accept:find(supported_types[i], 1, true) or 1000) < (accept:find(ret, 1, true) or 1000) then | |
50 ret = supported_types[i]; | |
51 end | |
52 end | |
53 return ret; | |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
54 end |
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
55 |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
56 local function encode(type, s) |
3813 | 57 if type == "application/json" then |
58 return json.encode(jsonmap.st2json(s)); | |
59 elseif type == "text/plain" then | |
60 return s:get_child_text("body") or ""; | |
61 end | |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
62 return tostring(s); |
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
63 end |
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
64 |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
65 local function handle_post(event) |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
66 local request, response = event.request, event.response; |
3802
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
67 if not request.headers.authorization then |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
68 response.headers.www_authenticate = ("%s realm=%q"):format(auth_type, module.host.."/"..module.name); |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
69 return 401; |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
70 elseif not check_credentials(request) then |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
71 return 401; |
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
72 end |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
73 local payload, err = parse(request.headers.content_type, request.body); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
74 if not payload then |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
75 -- parse fail |
3843
c065b7670c89
mod_rest: Return a friendly message for parse errors
Kim Alvefur <zash@zash.se>
parents:
3842
diff
changeset
|
76 return errors.new({ code = 400, text = "Failed to parse payload" }, { error = err, type = request.headers.content_type, data = request.body }); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
77 end |
3801
d59fb4dcf100
mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents:
3799
diff
changeset
|
78 if payload.attr.xmlns then |
3804
d74509cd35fb
mod_rest: Use HTTP status 422 for stanza problems
Kim Alvefur <zash@zash.se>
parents:
3803
diff
changeset
|
79 return errors.new({ code = 422, text = "'xmlns' attribute must be empty" }); |
3805
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3804
diff
changeset
|
80 elseif payload.name ~= "message" and payload.name ~= "presence" and payload.name ~= "iq" then |
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3804
diff
changeset
|
81 return errors.new({ code = 422, text = "Invalid stanza, must be 'message', 'presence' or 'iq'." }); |
3801
d59fb4dcf100
mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents:
3799
diff
changeset
|
82 end |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
83 local to = jid.prep(payload.attr.to); |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
84 if not to then |
3804
d74509cd35fb
mod_rest: Use HTTP status 422 for stanza problems
Kim Alvefur <zash@zash.se>
parents:
3803
diff
changeset
|
85 return errors.new({ code = 422, text = "Invalid destination JID" }); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
86 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
87 local from = module.host; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
88 if allow_any_source and payload.attr.from then |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
89 from = jid.prep(payload.attr.from); |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
90 if not from then |
3804
d74509cd35fb
mod_rest: Use HTTP status 422 for stanza problems
Kim Alvefur <zash@zash.se>
parents:
3803
diff
changeset
|
91 return errors.new({ code = 422, text = "Invalid source JID" }); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
92 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
93 if validate_from_addresses and not jid.compare(from, module.host) then |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
94 return errors.new({ code = 403, text = "Source JID must belong to current host" }); |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
95 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
96 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
97 payload.attr = { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
98 from = from, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
99 to = to, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
100 id = payload.attr.id or id.medium(), |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
101 type = payload.attr.type, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
102 ["xml:lang"] = payload.attr["xml:lang"], |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
103 }; |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
104 module:log("debug", "Received[rest]: %s", payload:top_tag()); |
3816
8473fd2d09c1
mod_rest: Default to replying with same type as request
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
105 local send_type = decide_type((request.headers.accept or "") ..",".. request.headers.content_type) |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
106 if payload.name == "iq" then |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
107 if payload.attr.type ~= "get" and payload.attr.type ~= "set" then |
3804
d74509cd35fb
mod_rest: Use HTTP status 422 for stanza problems
Kim Alvefur <zash@zash.se>
parents:
3803
diff
changeset
|
108 return errors.new({ code = 422, text = "'iq' stanza must be of type 'get' or 'set'" }); |
3832
0d4146cf9fbc
mod_rest: Enforce single child policy for outgoing it stanzas
Kim Alvefur <zash@zash.se>
parents:
3825
diff
changeset
|
109 elseif #payload.tags ~= 1 then |
0d4146cf9fbc
mod_rest: Enforce single child policy for outgoing it stanzas
Kim Alvefur <zash@zash.se>
parents:
3825
diff
changeset
|
110 return errors.new({ code = 422, text = "'iq' stanza must have exactly one child tag" }); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
111 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
112 return module:send_iq(payload):next( |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
113 function (result) |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
114 module:log("debug", "Sending[rest]: %s", result.stanza:top_tag()); |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
115 response.headers.content_type = send_type; |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
116 return encode(send_type, result.stanza); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
117 end, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
118 function (error) |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
119 if error.context.stanza then |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
120 response.headers.content_type = send_type; |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
121 module:log("debug", "Sending[rest]: %s", error.context.stanza:top_tag()); |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
122 return encode(send_type, error.context.stanza); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
123 else |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
124 return error; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
125 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
126 end); |
3805
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3804
diff
changeset
|
127 else |
3796
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3795
diff
changeset
|
128 local origin = {}; |
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3795
diff
changeset
|
129 function origin.send(stanza) |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
130 module:log("debug", "Sending[rest]: %s", stanza:top_tag()); |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
131 response.headers.content_type = send_type; |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
132 response:send(encode(send_type, stanza)); |
3796
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3795
diff
changeset
|
133 return true; |
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3795
diff
changeset
|
134 end |
3814
0dede5b0ab27
mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents:
3813
diff
changeset
|
135 module:send(payload, origin); |
0dede5b0ab27
mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents:
3813
diff
changeset
|
136 return 202; |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
137 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
138 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
139 |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
140 -- Handle stanzas submitted via HTTP |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
141 module:depends("http"); |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
142 module:provides("http", { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
143 route = { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
144 POST = handle_post; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
145 }; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
146 }); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
147 |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
148 -- Forward stanzas from XMPP to HTTP and return any reply |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
149 local rest_url = module:get_option_string("rest_callback_url", nil); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
150 if rest_url then |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
151 local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml"); |
3813 | 152 if send_type == "json" then |
153 send_type = "application/json"; | |
154 end | |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
155 |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
156 module:set_status("info", "Not yet connected"); |
3861
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
157 http.request(rest_url, { |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
158 method = "OPTIONS", |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
159 }, function (body, code, response) |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
160 if code == 0 then |
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
161 return module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, body); |
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
162 else |
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
163 module:set_status("info", "Connected"); |
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
164 end |
3861
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
165 if code == 200 and response.headers.accept then |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
166 send_type = decide_type(response.headers.accept); |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
167 module:log("debug", "Set 'rest_callback_content_type' = %q based on Accept header", send_type); |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
168 end |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
169 end); |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
170 |
3797
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
171 local code2err = { |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
172 [400] = { condition = "bad-request"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
173 [401] = { condition = "not-authorized"; type = "auth" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
174 [402] = { condition = "not-authorized"; type = "auth" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
175 [403] = { condition = "forbidden"; type = "auth" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
176 [404] = { condition = "item-not-found"; type = "cancel" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
177 [406] = { condition = "not-acceptable"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
178 [408] = { condition = "remote-server-timeout"; type = "wait" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
179 [409] = { condition = "conflict"; type = "cancel" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
180 [410] = { condition = "gone"; type = "cancel" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
181 [411] = { condition = "bad-request"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
182 [412] = { condition = "bad-request"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
183 [413] = { condition = "resource-constraint"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
184 [414] = { condition = "resource-constraint"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
185 [415] = { condition = "bad-request"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
186 [429] = { condition = "resource-constraint"; type = "wait" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
187 [431] = { condition = "resource-constraint"; type = "wait" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
188 |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
189 [500] = { condition = "internal-server-error"; type = "cancel" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
190 [501] = { condition = "feature-not-implemented"; type = "modify" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
191 [502] = { condition = "remote-server-timeout"; type = "wait" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
192 [503] = { condition = "service-unavailable"; type = "cancel" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
193 [504] = { condition = "remote-server-timeout"; type = "wait" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
194 [507] = { condition = "resource-constraint"; type = "wait" }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
195 }; |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
196 |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
197 local function handle_stanza(event) |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
198 local stanza, origin = event.stanza, event.origin; |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
199 local reply_needed = stanza.name == "iq"; |
3798
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
200 local receipt; |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
201 |
3824
a0b8ec44a36b
mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents:
3821
diff
changeset
|
202 if stanza.attr.type == "error" then |
a0b8ec44a36b
mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents:
3821
diff
changeset
|
203 reply_needed = false; |
a0b8ec44a36b
mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents:
3821
diff
changeset
|
204 end |
a0b8ec44a36b
mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents:
3821
diff
changeset
|
205 |
3798
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
206 if stanza.name == "message" and stanza.attr.id and stanza:get_child("urn:xmpp:receipts", "request") then |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
207 reply_needed = true; |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
208 receipt = st.stanza("received", { xmlns = "urn:xmpp:receipts", id = stanza.id }); |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
209 end |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
210 |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
211 local request_body = encode(send_type, stanza); |
3799
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
212 |
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
213 -- Keep only the top level element and let the rest be GC'd |
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
214 stanza = st.clone(stanza, true); |
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
215 |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
216 module:log("debug", "Sending[rest]: %s", stanza:top_tag()); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
217 http.request(rest_url, { |
3799
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
218 body = request_body, |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
219 headers = { |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
220 ["Content-Type"] = send_type, |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
221 ["Content-Language"] = stanza.attr["xml:lang"], |
3813 | 222 Accept = table.concat(supported_types, ", "); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
223 }, |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
224 }, function (body, code, response) |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
225 if code == 0 then |
3864
d845475c75f3
mod_rest: Process results even on internal errors with HTTP request
Kim Alvefur <zash@zash.se>
parents:
3862
diff
changeset
|
226 module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, body); |
3866
c0df50ce96f0
mod_rest: Handle internal http request errors early and then return
Kim Alvefur <zash@zash.se>
parents:
3865
diff
changeset
|
227 origin.send(st.error_reply(stanza, "wait", "recipient-unavailable", body)); |
c0df50ce96f0
mod_rest: Handle internal http request errors early and then return
Kim Alvefur <zash@zash.se>
parents:
3865
diff
changeset
|
228 return; |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
229 else |
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
230 module:set_status("info", "Connected"); |
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
231 end |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
232 if (code == 202 or code == 204) and not reply_needed then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
233 -- Delivered, no reply |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
234 return; |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
235 end |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
236 local reply; |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
237 |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
238 local parsed, err = parse(response.headers["content-type"], body); |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
239 if not parsed then |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
240 module:log("warn", "Failed parsing data from REST callback: %s, %q", err, body); |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
241 elseif parsed.name ~= stanza.name then |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
242 module:log("warn", "REST callback responded with the wrong stanza type, got %s but expected %s", parsed.name, stanza.name); |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
243 else |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
244 parsed.attr = { |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
245 from = stanza.attr.to, |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
246 to = stanza.attr.from, |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
247 id = parsed.attr.id or id.medium(); |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
248 type = parsed.attr.type, |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
249 ["xml:lang"] = parsed.attr["xml:lang"], |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
250 }; |
3821
11272a3233ce
mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents:
3816
diff
changeset
|
251 if parsed.name == "message" and parsed.attr.type == "groupchat" then |
11272a3233ce
mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents:
3816
diff
changeset
|
252 parsed.attr.to = jid.bare(stanza.attr.from); |
11272a3233ce
mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents:
3816
diff
changeset
|
253 end |
3858
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
254 if not stanza.attr.type and parsed:get_child("error") then |
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
255 parsed.attr.type = "error"; |
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
256 end |
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
257 if parsed.attr.type == "error" then |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
258 parsed.attr.id = stanza.attr.id; |
3858
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
259 elseif parsed.name == "iq" then |
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
260 parsed.attr.id = stanza.attr.id; |
29c39876c4af
mod_rest: Ensure iq responses have type result if they're not errors
Kim Alvefur <zash@zash.se>
parents:
3843
diff
changeset
|
261 parsed.attr.type = "result"; |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
262 end |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
263 reply = parsed; |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
264 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
265 |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
266 if not reply then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
267 local code_hundreds = code - (code % 100); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
268 if code_hundreds == 200 then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
269 reply = st.reply(stanza); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
270 if stanza.name ~= "iq" then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
271 reply.attr.id = id.medium(); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
272 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
273 -- TODO presence/status=body ? |
3797
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
274 elseif code2err[code] then |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3796
diff
changeset
|
275 reply = st.error_reply(stanza, errors.new(code, nil, code2err)); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
276 elseif code_hundreds == 400 then |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
277 reply = st.error_reply(stanza, "modify", "bad-request", body); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
278 elseif code_hundreds == 500 then |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
279 reply = st.error_reply(stanza, "cancel", "internal-server-error", body); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
280 else |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
281 reply = st.error_reply(stanza, "cancel", "undefined-condition", body); |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
282 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
283 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
284 |
3798
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
285 if receipt then |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
286 reply:add_direct_child(receipt); |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
287 end |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
288 |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
289 module:log("debug", "Received[rest]: %s", reply:top_tag()); |
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
290 |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
291 origin.send(reply); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
292 end); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
293 |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
294 return true; |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
295 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
296 |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
297 if module:get_host_type() == "component" then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
298 module:hook("iq/bare", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
299 module:hook("message/bare", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
300 module:hook("presence/bare", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
301 module:hook("iq/full", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
302 module:hook("message/full", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
303 module:hook("presence/full", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
304 module:hook("iq/host", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
305 module:hook("message/host", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
306 module:hook("presence/host", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
307 else |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
308 -- Don't override everything on normal VirtualHosts |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
309 module:hook("iq/host", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
310 module:hook("message/host", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
311 module:hook("presence/host", handle_stanza, -1); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
312 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
313 end |
3842
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
314 |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
315 local http_server = require "net.http.server"; |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
316 module:hook_object_event(http_server, "http-error", function (event) |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
317 local request, response = event.request, event.response; |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
318 if true or decide_type(request and request.headers.accept or "") == "application/json" then |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
319 if response then |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
320 response.headers.content_type = "application/json"; |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
321 end |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
322 return json.encode({ |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
323 type = "error", |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
324 error = event.error, |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
325 code = event.code, |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
326 }); |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
327 end |
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
328 end, 10); |