annotate mod_rest/mod_rest.lua @ 4242:6a91d217acc9

mod_rest: Add whitespace to improve readability, code navigation I use {} in vim a lot.
author Kim Alvefur <zash@zash.se>
date Thu, 12 Nov 2020 20:37:54 +0100
parents 07ae583bc565
children 07c11080027e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
7 local encodings = require "util.encodings";
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
8 local base64 = encodings.base64;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
9 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
10 local http = require "net.http";
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
11 local id = require "util.id";
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
12 local jid = require "util.jid";
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
13 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
14 local st = require "util.stanza";
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
15 local um = require "core.usermanager";
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
16 local xml = require "util.xml";
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
17 local have_cbor, cbor = pcall(require, "cbor");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
18
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
19 local jsonmap = module:require"jsonmap";
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
20
3915
80dffbbd056b mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents: 3911
diff changeset
21 local tokens = module:depends("tokenauth");
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
22
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
23 local auth_mechanisms = module:get_option_set("rest_auth_mechanisms", { "Basic", "Bearer" });
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
24
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
25 local www_authenticate_header;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
26 do
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
27 local header, realm = {}, module.host.."/"..module.name;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
28 for mech in auth_mechanisms do
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
29 header[#header+1] = ("%s realm=%q"):format(mech, realm);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
30 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
31 www_authenticate_header = table.concat(header, ", ");
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
32 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
33
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
34 -- Bearer token
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
35 local function check_credentials(request)
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
36 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$");
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
37 if not (auth_type and auth_data) or not auth_mechanisms:contains(auth_type) then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
38 return false;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
39 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
40
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
41 if auth_type == "Basic" then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
42 local creds = base64.decode(auth_data);
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
43 if not creds then return false; end
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
44 local username, password = string.match(creds, "^([^:]+):(.*)$");
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
45 if not username then return false; end
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
46 username, password = encodings.stringprep.nodeprep(username), encodings.stringprep.saslprep(password);
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
47 if not username then return false; end
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
48 if not um.test_password(username, module.host, password) then
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
49 return false;
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
50 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
51 return { username = username, host = module.host };
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
52 elseif auth_type == "Bearer" then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
53 local token_info = tokens.get_token_info(auth_data);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
54 if not token_info or not token_info.session then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
55 return false;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
56 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
57 return token_info.session;
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
58 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
59 return nil;
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
60 end
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
61
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
62 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
63 mimetype = mimetype and mimetype:match("^[^; ]*");
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
64 if mimetype == "application/xmpp+xml" then
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
65 return xml.parse(data);
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
66 elseif mimetype == "application/json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
67 local parsed, err = json.decode(data);
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
68 if not parsed then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
69 return parsed, err;
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
70 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
71 return jsonmap.json2st(parsed);
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
72 elseif mimetype == "application/cbor" and have_cbor then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
73 local parsed, err = cbor.decode(data);
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
74 if not parsed then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
75 return parsed, err;
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
76 end
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
77 return jsonmap.json2st(parsed);
3911
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
78 elseif mimetype == "application/x-www-form-urlencoded"then
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
79 local parsed = http.formdecode(data);
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
80 if type(parsed) == "string" then
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
81 return parse("text/plain", parsed);
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
82 end
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
83 for i = #parsed, 1, -1 do
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
84 parsed[i] = nil;
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
85 end
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
86 return jsonmap.json2st(parsed);
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
87 elseif mimetype == "text/plain" then
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
88 return st.message({ type = "chat" }, data);
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
89 end
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
90 return nil, "unknown-payload-type";
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
91 end
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
92
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
93 local function decide_type(accept, supported_types)
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
94 -- assumes the accept header is sorted
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
95 local ret = supported_types[1];
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
96 for i = 2, #supported_types do
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
97 if (accept:find(supported_types[i], 1, true) or 1000) < (accept:find(ret, 1, true) or 1000) then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
98 ret = supported_types[i];
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
99 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
100 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
101 return ret;
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
102 end
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
103
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
104 local supported_inputs = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
105 "application/xmpp+xml",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
106 "application/json",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
107 "application/x-www-form-urlencoded",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
108 "text/plain",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
109 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
110
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
111 local supported_outputs = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
112 "application/xmpp+xml",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
113 "application/json",
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
114 "application/x-www-form-urlencoded",
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
115 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
116
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
117 if have_cbor then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
118 table.insert(supported_inputs, "application/cbor");
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
119 table.insert(supported_outputs, "application/cbor");
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
120 end
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
121
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
122 -- Only { string : string } can be form-encoded, discard the rest
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
123 -- (jsonmap also discards anything unknown or unsupported)
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
124 local function flatten(t)
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
125 local form = {};
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
126 for k, v in pairs(t) do
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
127 if type(v) == "string" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
128 form[k] = v;
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
129 elseif type(v) == "number" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
130 form[k] = tostring(v);
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
131 elseif v == true then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
132 form[k] = "";
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
133 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
134 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
135 return form;
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
136 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
137
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
138 local function encode(type, s)
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
139 if type == "application/json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
140 return json.encode(jsonmap.st2json(s));
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
141 elseif type == "application/x-www-form-urlencoded" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
142 return http.formencode(flatten(jsonmap.st2json(s)));
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
143 elseif type == "application/cbor" then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
144 return cbor.encode(jsonmap.st2json(s));
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
145 elseif type == "text/plain" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
146 return s:get_child_text("body") or "";
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
147 end
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
148 return tostring(s);
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
149 end
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
150
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
151 local post_errors = {
3971
ae5ac41c391d mod_rest: Improve auth error reporting
Kim Alvefur <zash@zash.se>
parents: 3933
diff changeset
152 noauthz = { code = 401, type = "auth", condition = "not-authorized", text = "No credentials provided" },
ae5ac41c391d mod_rest: Improve auth error reporting
Kim Alvefur <zash@zash.se>
parents: 3933
diff changeset
153 unauthz = { code = 403, type = "auth", condition = "not-authorized", text = "Credentials not accepted" },
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
154 parse = { code = 400, condition = "not-well-formed", text = "Failed to parse payload", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
155 xmlns = { code = 422, condition = "invalid-namespace", text = "'xmlns' attribute must be empty", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
156 name = { code = 422, condition = "unsupported-stanza-type", text = "Invalid stanza, must be 'message', 'presence' or 'iq'.", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
157 to = { code = 422, condition = "improper-addressing", text = "Invalid destination JID", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
158 from = { code = 422, condition = "invalid-from", text = "Invalid source JID", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
159 post_auth = { code = 403, condition = "not-authorized", text = "Not authorized to send stanza with requested 'from'", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
160 iq_type = { code = 422, condition = "invalid-xml", text = "'iq' stanza must be of type 'get' or 'set'", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
161 iq_tags = { code = 422, condition = "bad-format", text = "'iq' stanza must have exactly one child tag", },
4036
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
162 mediatype = { code = 415, condition = "bad-format", text = "Unsupported media type" },
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
163 };
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
164
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
165 local function handle_post(event)
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
166 local request, response = event.request, event.response;
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
167 local from;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
168 local origin;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
169
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
170 if not request.headers.authorization then
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
171 response.headers.www_authenticate = www_authenticate_header;
3971
ae5ac41c391d mod_rest: Improve auth error reporting
Kim Alvefur <zash@zash.se>
parents: 3933
diff changeset
172 return errors.new("noauthz", nil, post_errors);
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
173 else
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
174 origin = check_credentials(request);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
175 if not origin then
3971
ae5ac41c391d mod_rest: Improve auth error reporting
Kim Alvefur <zash@zash.se>
parents: 3933
diff changeset
176 return errors.new("unauthz", nil, post_errors);
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
177 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
178 from = jid.join(origin.username, origin.host, origin.resource);
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
179 end
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
180 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
181 if not payload then
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
182 -- parse fail
4036
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
183 local ctx = { error = err, type = request.headers.content_type, data = request.body, };
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
184 if err == "unknown-payload-type" then
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
185 return errors.new("mediatype", ctx, post_errors);
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
186 end
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
187 return errors.new("parse", ctx, post_errors);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
188 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
189
3801
d59fb4dcf100 mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents: 3799
diff changeset
190 if payload.attr.xmlns then
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
191 return errors.new("xmlns", nil, post_errors);
3805
683b06c0348f mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents: 3804
diff changeset
192 elseif payload.name ~= "message" and payload.name ~= "presence" and payload.name ~= "iq" then
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
193 return errors.new("name", nil, post_errors);
3801
d59fb4dcf100 mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents: 3799
diff changeset
194 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
195
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
196 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
197 if not to then
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
198 return errors.new("to", nil, post_errors);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
199 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
200
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
201 if payload.attr.from then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
202 local requested_from = jid.prep(payload.attr.from);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
203 if not requested_from then
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
204 return errors.new("from", nil, post_errors);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
205 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
206 if jid.compare(requested_from, from) then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
207 from = requested_from;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
208 else
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
209 return errors.new("from_auth", nil, post_errors);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
210 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
211 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
212
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
213 payload.attr = {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
214 from = from,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
215 to = to,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
216 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
217 type = payload.attr.type,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
218 ["xml:lang"] = payload.attr["xml:lang"],
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
219 };
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
220
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
221 module:log("debug", "Received[rest]: %s", payload:top_tag());
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
222 local send_type = decide_type((request.headers.accept or "") ..",".. request.headers.content_type, supported_outputs)
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
223 if payload.name == "iq" then
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
224 function origin.send(stanza)
3926
f77ae9685eb6 mod_rest: Fix routing to self-jid (thanks jonas’)
Kim Alvefur <zash@zash.se>
parents: 3925
diff changeset
225 module:send(stanza);
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
226 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
227
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
228 if payload.attr.type ~= "get" and payload.attr.type ~= "set" then
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
229 return errors.new("iq_type", nil, post_errors);
3832
0d4146cf9fbc mod_rest: Enforce single child policy for outgoing it stanzas
Kim Alvefur <zash@zash.se>
parents: 3825
diff changeset
230 elseif #payload.tags ~= 1 then
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
231 return errors.new("iq_tags", nil, post_errors);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
232 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
233
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
234 return module:send_iq(payload, origin):next(
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
235 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
236 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
237 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
238 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
239 end,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
240 function (error)
3909
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
241 if not errors.is_err(error) then
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
242 module:log("error", "Uncaught native error: %s", error);
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
243 return select(2, errors.coerce(nil, error));
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
244 elseif error.context and error.context.stanza then
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
245 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
246 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
247 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
248 else
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
249 return error;
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
250 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
251 end);
3805
683b06c0348f mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents: 3804
diff changeset
252 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
253 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
254 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
255 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
256 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
257 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
258 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
259
3814
0dede5b0ab27 mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents: 3813
diff changeset
260 module:send(payload, origin);
0dede5b0ab27 mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents: 3813
diff changeset
261 return 202;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
262 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
263 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
264
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
265 -- Handle stanzas submitted via HTTP
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
266 module:depends("http");
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
267 module:provides("http", {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
268 route = {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
269 POST = handle_post;
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
270 };
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
271 });
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
272
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
273 -- 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
274 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
275 if rest_url then
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
276 local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml");
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
277 if send_type == "json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
278 send_type = "application/json";
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
279 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
280
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
281 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
282 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
283 method = "OPTIONS",
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
284 }, function (body, code, response)
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
285 if code == 0 then
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
286 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
287 else
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
288 module:set_status("info", "Connected");
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
289 end
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
290 if code == 200 and response.headers.accept then
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
291 send_type = decide_type(response.headers.accept, supported_outputs);
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
292 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
293 end
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
294 end);
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
295
3797
ed5d7586a61e mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents: 3796
diff changeset
296 local code2err = {
ed5d7586a61e mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents: 3796
diff changeset
297 [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
298 [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
299 [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
300 [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
301 [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
302 [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
303 [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
304 [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
305 [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
306 [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
307 [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
308 [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
309 [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
310 [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
311 [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
312 [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
313
ed5d7586a61e mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents: 3796
diff changeset
314 [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
315 [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
316 [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
317 [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
318 [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
319 [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
320 };
ed5d7586a61e mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents: 3796
diff changeset
321
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
322 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
323 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
324 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
325 local receipt;
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
326
3824
a0b8ec44a36b mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents: 3821
diff changeset
327 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
328 reply_needed = false;
a0b8ec44a36b mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents: 3821
diff changeset
329 end
a0b8ec44a36b mod_rest: Stanzas of type error don't need a reply
Kim Alvefur <zash@zash.se>
parents: 3821
diff changeset
330
3798
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
331 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
332 reply_needed = true;
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
333 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
334 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
335
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
336 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
337
a1f1f703d604 mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents: 3798
diff changeset
338 -- 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
339 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
340
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
341 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
342 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
343 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
344 headers = {
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
345 ["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
346 ["Content-Language"] = stanza.attr["xml:lang"],
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
347 Accept = table.concat(supported_inputs, ", ");
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
348 },
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
349 }, function (body, code, response)
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
350 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
351 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
352 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
353 return;
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
354 else
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
355 module:set_status("info", "Connected");
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
356 end
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
357 local reply;
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
358
3867
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
359 if code == 202 or code == 204 then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
360 if not reply_needed then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
361 -- Delivered, no reply
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
362 return;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
363 end
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
364 else
3867
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
365 local parsed, err = parse(response.headers["content-type"], body);
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
366 if not parsed then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
367 module:log("warn", "Failed parsing data from REST callback: %s, %q", err, body);
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
368 elseif parsed.name ~= stanza.name then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
369 module:log("warn", "REST callback responded with the wrong stanza type, got %s but expected %s", parsed.name, stanza.name);
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
370 else
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
371 parsed.attr = {
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
372 from = stanza.attr.to,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
373 to = stanza.attr.from,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
374 id = parsed.attr.id or id.medium();
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
375 type = parsed.attr.type,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
376 ["xml:lang"] = parsed.attr["xml:lang"],
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
377 };
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
378 if parsed.name == "message" and parsed.attr.type == "groupchat" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
379 parsed.attr.to = jid.bare(stanza.attr.from);
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
380 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
381 if not stanza.attr.type and parsed:get_child("error") then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
382 parsed.attr.type = "error";
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
383 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
384 if parsed.attr.type == "error" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
385 parsed.attr.id = stanza.attr.id;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
386 elseif parsed.name == "iq" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
387 parsed.attr.id = stanza.attr.id;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
388 parsed.attr.type = "result";
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
389 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
390 reply = parsed;
3821
11272a3233ce mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents: 3816
diff changeset
391 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
392 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
393
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
394 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
395 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
396 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
397 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
398 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
399 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
400 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
401 -- 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
402 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
403 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
404 elseif code_hundreds == 400 then
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
405 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
406 elseif code_hundreds == 500 then
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
407 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
408 else
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
409 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
410 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
411 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
412
3798
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
413 if receipt then
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
414 reply:add_direct_child(receipt);
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
415 end
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
416
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
417 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
418
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
419 origin.send(reply);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
420 end);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
421
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
422 return true;
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
423 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
424
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
425 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
426 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
427 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
428 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
429 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
430 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
431 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
432 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
433 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
434 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
435 else
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
436 -- 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
437 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
438 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
439 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
440 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
441 end
3842
501c7edc8c37 mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents: 3832
diff changeset
442
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
443 local supported_errors = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
444 "text/html",
3931
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
445 "application/xmpp+xml",
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
446 "application/json",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
447 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
448
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
449 local http_server = require "net.http.server";
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
450 module:hook_object_event(http_server, "http-error", function (event)
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
451 local request, response = event.request, event.response;
3931
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
452 local response_as = decide_type(request and request.headers.accept or "", supported_errors);
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
453 if response_as == "application/xmpp+xml" then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
454 if response then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
455 response.headers.content_type = "application/xmpp+xml";
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
456 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
457 local stream_error = st.stanza("error", { xmlns = "http://etherx.jabber.org/streams" });
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
458 if event.error then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
459 stream_error:tag(event.error.condition, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }):up();
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
460 if event.error.text then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
461 stream_error:text_tag("text", event.error.text, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' });
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
462 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
463 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
464 return tostring(stream_error);
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
465 elseif response_as == "application/json" then
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
466 if response then
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
467 response.headers.content_type = "application/json";
3842
501c7edc8c37 mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents: 3832
diff changeset
468 end
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
469 return json.encode({
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
470 type = "error",
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
471 error = event.error,
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
472 code = event.code,
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
473 });
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
474 end
3933
93147b89ea67 mod_rest: Avoid interfering with mod_http_oauth2 errors (fixes #1500)
Kim Alvefur <zash@zash.se>
parents: 3931
diff changeset
475 end, 1);