Annotate

mod_rest/mod_rest.lua @ 6310:30adcea825c3

mod_conversejs: Fix hostname set as default username (thanks roughnecks) In login mode, it seems jid is used as default value in the login field but it was only needed in anonymous mode.
author Kim Alvefur <zash@zash.se>
date Wed, 18 Jun 2025 14:28:38 +0200
parent 6272:ed6fa901cf94
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 --
4920
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
3 -- Copyright (c) 2019-2022 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
5701
0cffeff2cd1d mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents: 5585
diff changeset
23 -- Lower than the default c2s size limit to account for possible JSON->XML size increase
0cffeff2cd1d mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents: 5585
diff changeset
24 local stanza_size_limit = module:get_option_number("rest_stanza_size_limit", 1024 * 192);
0cffeff2cd1d mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents: 5585
diff changeset
25
5960
d5e6617e47cc mod_rest: Fix to allow case sensitive HTTP authentication scheme
Kim Alvefur <zash@zash.se>
parents: 5954
diff changeset
26 local auth_mechanisms = module:get_option_set("rest_auth_mechanisms", { "Basic", "Bearer" }) / string.lower;
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
27
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
28 local www_authenticate_header;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
29 do
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
30 local header, realm = {}, module.host.."/"..module.name;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
31 for mech in auth_mechanisms do
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
32 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
33 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
34 www_authenticate_header = table.concat(header, ", ");
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
35 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
36
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
37 local post_errors = errors.init("mod_rest", {
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
38 noauthz = { code = 401; type = "auth"; condition = "not-authorized"; text = "No credentials provided" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
39 unauthz = { code = 403; type = "auth"; condition = "not-authorized"; text = "Credentials not accepted" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
40 malformauthz = { code = 403; type = "auth"; condition = "not-authorized"; text = "Credentials malformed" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
41 prepauthz = { code = 403; type = "auth"; condition = "not-authorized"; text = "Credentials failed stringprep" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
42 parse = { code = 400; type = "modify"; condition = "not-well-formed"; text = "Failed to parse payload" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
43 xmlns = { code = 422; type = "modify"; condition = "invalid-namespace"; text = "'xmlns' attribute must be empty" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
44 name = { code = 422; type = "modify"; condition = "unsupported-stanza-type"; text = "Invalid stanza, must be 'message', 'presence' or 'iq'." };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
45 to = { code = 422; type = "modify"; condition = "improper-addressing"; text = "Invalid destination JID" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
46 from = { code = 422; type = "modify"; condition = "invalid-from"; text = "Invalid source JID" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
47 from_auth = { code = 403; type = "auth"; condition = "not-authorized"; text = "Not authorized to send stanza with requested 'from'" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
48 iq_type = { code = 422; type = "modify"; condition = "invalid-xml"; text = "'iq' stanza must be of type 'get' or 'set'" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
49 iq_tags = { code = 422; type = "modify"; condition = "bad-format"; text = "'iq' stanza must have exactly one child tag" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
50 mediatype = { code = 415; type = "cancel"; condition = "bad-format"; text = "Unsupported media type" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
51 size = { code = 413; type = "modify"; condition = "resource-constraint", text = "Payload too large" };
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
52 });
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
53
5993
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
54 local token_session_errors = errors.init("mod_tokenauth", {
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
55 ["internal-error"] = { code = 500; type = "wait"; condition = "internal-server-error" };
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
56 ["invalid-token-format"] = { code = 403; type = "auth"; condition = "not-authorized"; text = "Credentials malformed" };
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
57 ["not-authorized"] = { code = 403; type = "auth"; condition = "not-authorized"; text = "Credentials not accepted" };
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
58 });
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
59
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
60 local function check_credentials(request) -- > session | boolean, error
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
61 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$");
5962
667ce80937fa mod_rest: Fix authentication
Kim Alvefur <zash@zash.se>
parents: 5961
diff changeset
62 auth_type = auth_type and auth_type:lower();
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
63 if not (auth_type and auth_data) or not auth_mechanisms:contains(auth_type) then
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
64 return nil, post_errors.new("noauthz", { request = request });
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
65 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
66
6272
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
67 if auth_type == "basic" and module:get_host_type() == "local" then
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
68 local creds = base64.decode(auth_data);
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
69 if not creds then
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
70 return nil, post_errors.new("malformauthz", { request = request });
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
71 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
72 local username, password = string.match(creds, "^([^:]+):(.*)$");
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
73 if not username then
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
74 return nil, post_errors.new("malformauthz", { request = request });
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
75 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
76 username, password = encodings.stringprep.nodeprep(username), encodings.stringprep.saslprep(password);
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
77 if not username or not password then
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
78 return false, post_errors.new("prepauthz", { request = request });
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
79 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
80 if not um.test_password(username, module.host, password) then
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
81 return false, post_errors.new("unauthz", { request = request });
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
82 end
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
83 return { username = username; host = module.host };
6272
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
84 elseif auth_type == "basic" and module:get_host_type() == "component" then
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
85 local component_secret = module:get_option_string("component_secret");
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
86 local creds = base64.decode(auth_data);
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
87 if creds ~= module.host .. ":" .. component_secret then
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
88 return nil, post_errors.new("malformauthz", { request = request });
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
89 end
ed6fa901cf94 mod_rest: Enable HTTP Basic authentication for Components
Kim Alvefur <zash@zash.se>
parents: 6244
diff changeset
90 return { host = module.host };
5960
d5e6617e47cc mod_rest: Fix to allow case sensitive HTTP authentication scheme
Kim Alvefur <zash@zash.se>
parents: 5954
diff changeset
91 elseif auth_type == "bearer" then
5001
cb19cb1c03d6 mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents: 4988
diff changeset
92 if tokens.get_token_session then
5993
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
93 local token_session, err = tokens.get_token_session(auth_data);
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
94 if not token_session then
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
95 return false, token_session_errors.new(err or "not-authorized", { request = request });
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
96 end
a0d77b427d50 mod_rest: Wrap mod_tokenauth errors
Kim Alvefur <zash@zash.se>
parents: 5981
diff changeset
97 return token_session;
5001
cb19cb1c03d6 mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents: 4988
diff changeset
98 else -- COMPAT w/0.12
cb19cb1c03d6 mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents: 4988
diff changeset
99 local token_info = tokens.get_token_info(auth_data);
cb19cb1c03d6 mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents: 4988
diff changeset
100 if not token_info or not token_info.session then
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
101 return false, post_errors.new("unauthz", { request = request });
5001
cb19cb1c03d6 mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents: 4988
diff changeset
102 end
cb19cb1c03d6 mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents: 4988
diff changeset
103 return token_info.session;
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
104 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
105 end
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
106 return nil, post_errors.new("noauthz", { request = request });
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
107 end
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
108
4734
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
109 if module:get_option_string("authentication") == "anonymous" and module:get_option_boolean("anonymous_rest") then
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
110 www_authenticate_header = nil;
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
111 function check_credentials(request) -- luacheck: ignore 212/request
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
112 return {
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
113 username = id.medium():lower();
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
114 host = module.host;
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
115 }
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
116 end
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
117 end
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
118
4941
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
119 local function event_suffix(jid_to)
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
120 local node, _, resource = jid.split(jid_to);
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
121 if node then
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
122 if resource then
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
123 return '/full';
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
124 else
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
125 return '/bare';
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
126 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
127 else
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
128 return '/host';
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
129 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
130 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
131
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
132
4735
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
133 -- TODO This ought to be handled some way other than duplicating this
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
134 -- core.stanza_router code here.
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
135 local function compat_preevents(origin, stanza) --> boolean : handled
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
136 local to = stanza.attr.to;
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
137 local node, host, resource = jid.split(to);
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
138
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
139 local to_type, to_self;
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
140 if node then
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
141 if resource then
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
142 to_type = '/full';
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
143 else
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
144 to_type = '/bare';
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
145 if node == origin.username and host == origin.host then
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
146 stanza.attr.to = nil;
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
147 to_self = true;
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
148 end
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
149 end
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
150 else
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
151 if host then
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
152 to_type = '/host';
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
153 else
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
154 to_type = '/bare';
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
155 to_self = true;
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
156 end
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
157 end
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
158
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
159 local event_data = { origin = origin; stanza = stanza; to_self = to_self };
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
160
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
161 local result = module:fire_event("pre-stanza", event_data);
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
162 if result ~= nil then return true end
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
163 if module:fire_event('pre-' .. stanza.name .. to_type, event_data) then return true; end -- do preprocessing
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
164 return false
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
165 end
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
166
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
167 -- (table, string) -> table
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
168 local function amend_from_path(data, path)
5981
eef6cb08f9e7 mod_rest: Fix to allow underscores in path of HTTP GET to iq-get mapping
Kim Alvefur <zash@zash.se>
parents: 5962
diff changeset
169 local st_kind, st_type, st_to = path:match("^([mpi]%w+)/([%w_]+)/(.*)$");
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
170 if not st_kind then return; end
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
171 if st_kind == "iq" and st_type ~= "get" and st_type ~= "set" then
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
172 -- GET /iq/disco/jid
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
173 data = {
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
174 kind = "iq";
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
175 [st_type] = st_type == "ping" or data or {};
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
176 };
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
177 else
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
178 data.kind = st_kind;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
179 data.type = st_type;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
180 end
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
181 if st_to and st_to ~= "" then
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
182 data.to = st_to;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
183 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
184 return data;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
185 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
186
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
187 local function parse(mimetype, data, path) --> Stanza, error enum
3825
802087d3155a mod_rest: Fix traceback on missing content-type header
Kim Alvefur <zash@zash.se>
parents: 3824
diff changeset
188 mimetype = mimetype and mimetype:match("^[^; ]*");
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
189 if mimetype == "application/xmpp+xml" then
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
190 return xml.parse(data);
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
191 elseif mimetype == "application/json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
192 local parsed, err = json.decode(data);
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
193 if not parsed then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
194 return parsed, err;
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
195 end
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
196 if path then
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
197 parsed = amend_from_path(parsed, path);
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
198 if not parsed then return nil, "invalid-path"; end
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
199 end
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
200 return jsonmap.json2st(parsed);
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
201 elseif mimetype == "application/cbor" and have_cbor then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
202 local parsed, err = cbor.decode(data);
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
203 if not parsed then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
204 return parsed, err;
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
205 end
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
206 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
207 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
208 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
209 if type(parsed) == "string" then
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
210 -- This should reject GET /iq/query/to?messagebody
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
211 if path then
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
212 return nil, "invalid-query";
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
213 end
3911
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
214 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
215 end
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
216 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
217 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
218 end
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
219 if path then
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
220 parsed = amend_from_path(parsed, path);
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
221 if not parsed then return nil, "invalid-path"; end
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
222 end
3911
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
223 return jsonmap.json2st(parsed);
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
224 elseif mimetype == "text/plain" then
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
225 if not path then
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
226 return st.message({ type = "chat" }, data);
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
227 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
228 local parsed = {};
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
229 if path then
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
230 parsed = amend_from_path(parsed, path);
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
231 if not parsed then return nil, "invalid-path"; end
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
232 end
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
233 if parsed.kind == "message" then
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
234 parsed.body = data;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
235 elseif parsed.kind == "presence" then
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
236 parsed.show = data;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
237 else
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
238 return nil, "invalid-path";
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
239 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
240 return jsonmap.json2st(parsed);
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
241 elseif not mimetype and path then
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
242 local parsed = amend_from_path({}, path);
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
243 if not parsed then return nil, "invalid-path"; end
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
244 return jsonmap.json2st(parsed);
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
245 end
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
246 return nil, "unknown-payload-type";
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
247 end
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
248
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
249 local function decide_type(accept, supported_types)
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
250 -- assumes the accept header is sorted
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
251 local ret = supported_types[1];
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
252 for i = 2, #supported_types do
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
253 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
254 ret = supported_types[i];
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
255 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
256 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
257 return ret;
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
258 end
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
259
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
260 local supported_inputs = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
261 "application/xmpp+xml",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
262 "application/json",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
263 "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
264 "text/plain",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
265 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
266
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
267 local supported_outputs = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
268 "application/xmpp+xml",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
269 "application/json",
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
270 "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
271 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
272
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
273 if have_cbor then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
274 table.insert(supported_inputs, "application/cbor");
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
275 table.insert(supported_outputs, "application/cbor");
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
276 end
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
277
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
278 -- 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
279 -- (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
280 local function flatten(t)
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
281 local form = {};
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
282 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
283 if type(v) == "string" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
284 form[k] = v;
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
285 elseif type(v) == "number" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
286 form[k] = tostring(v);
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
287 elseif v == true then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
288 form[k] = "";
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
289 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
290 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
291 return form;
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
292 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
293
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
294 local function encode(type, s)
4918
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
295 if type == "text/plain" then
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
296 return s:get_child_text("body") or "";
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
297 elseif type == "application/xmpp+xml" then
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
298 return tostring(s);
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
299 end
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
300 local mapped, err = jsonmap.st2json(s);
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
301 if not mapped then return mapped, err; end
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
302 if type == "application/json" then
4918
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
303 return json.encode(mapped);
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
304 elseif type == "application/x-www-form-urlencoded" then
4918
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
305 return http.formencode(flatten(mapped));
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
306 elseif type == "application/cbor" then
4918
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
307 return cbor.encode(mapped);
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
308 end
4918
347e34c3c7e2 mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents: 4917
diff changeset
309 error "unsupported encoding";
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
310 end
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
311
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
312 -- GET → iq-get
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
313 local function parse_request(request, path)
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
314 if path and request.method == "GET" then
4506
508cb880b163 mod_rest: Fix typos [codespell]
Kim Alvefur <zash@zash.se>
parents: 4503
diff changeset
315 -- e.g. /version/{to}
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
316 if request.url.query then
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
317 return parse("application/x-www-form-urlencoded", request.url.query, "iq/"..path);
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
318 end
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
319 return parse(nil, nil, "iq/"..path);
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
320 else
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
321 return parse(request.headers.content_type, request.body, path);
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
322 end
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
323 end
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
324
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
325 local function handle_request(event, path)
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
326 local request, response = event.request, event.response;
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
327 local log = request.log or module._log;
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
328 local from;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
329 local origin;
4514
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
330 local echo = path == "echo";
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
331 if echo then path = nil; end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
332
4734
e58ec4b3cf90 mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents: 4727
diff changeset
333 if not request.headers.authorization and www_authenticate_header then
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
334 response.headers.www_authenticate = www_authenticate_header;
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
335 return post_errors.new("noauthz");
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
336 else
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
337 local err;
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
338 origin, err = check_credentials(request);
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
339 if not origin then
5954
9bcc26406b47 mod_rest: Return specific errors from credential checks
Kim Alvefur <zash@zash.se>
parents: 5953
diff changeset
340 return err or post_errors.new("unauthz");
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
341 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
342 from = jid.join(origin.username, origin.host, origin.resource);
5557
d7667d9ad96a mod_rest: Include full_jid property on origin
Kim Alvefur <zash@zash.se>
parents: 5334
diff changeset
343 origin.full_jid = from;
4727
e6f46d1b3337 mod_rest: Set type on temp session to satisfy certain auth checks
Kim Alvefur <zash@zash.se>
parents: 4699
diff changeset
344 origin.type = "c2s";
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
345 origin.log = log;
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
346 end
5701
0cffeff2cd1d mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents: 5585
diff changeset
347 if type(request.body) == "string" and #request.body > stanza_size_limit then
0cffeff2cd1d mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents: 5585
diff changeset
348 return post_errors.new("size", { size = #request.body; limit = stanza_size_limit });
0cffeff2cd1d mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents: 5585
diff changeset
349 end
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
350 local payload, err = parse_request(request, path);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
351 if not payload then
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
352 -- parse fail
4036
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
353 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
354 if err == "unknown-payload-type" then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
355 return post_errors.new("mediatype", ctx);
4036
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
356 end
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
357 return post_errors.new("parse", ctx);
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
358 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
359
4841
f69c5a443156 mod_rest: Fix nested message stanzas in XEP-0297 containers
Kim Alvefur <zash@zash.se>
parents: 4745
diff changeset
360 if (payload.attr.xmlns or "jabber:client") ~= "jabber:client" then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
361 return post_errors.new("xmlns");
3805
683b06c0348f mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents: 3804
diff changeset
362 elseif payload.name ~= "message" and payload.name ~= "presence" and payload.name ~= "iq" then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
363 return post_errors.new("name");
3801
d59fb4dcf100 mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents: 3799
diff changeset
364 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
365
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
366 local to = jid.prep(payload.attr.to);
4502
48afaec5d1de mod_rest: Allow empty @to to mean to=account is in normal XMPP
Kim Alvefur <zash@zash.se>
parents: 4488
diff changeset
367 if payload.attr.to and not to then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
368 return post_errors.new("to");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
369 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
370
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
371 if payload.attr.from then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
372 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
373 if not requested_from then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
374 return post_errors.new("from");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
375 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
376 if jid.compare(requested_from, from) then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
377 from = requested_from;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
378 else
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
379 return post_errors.new("from_auth");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
380 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
381 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
382
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
383 payload.attr = {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
384 from = from,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
385 to = to,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
386 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
387 type = payload.attr.type,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
388 ["xml:lang"] = payload.attr["xml:lang"],
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
389 };
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
390
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
391 log("debug", "Received[rest]: %s", payload:top_tag());
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
392 local send_type = decide_type((request.headers.accept or "") ..",".. (request.headers.content_type or ""), supported_outputs)
4514
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
393
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
394 if echo then
4917
9d0ec61c70a1 mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents: 4888
diff changeset
395 local ret, err = errors.coerce(encode(send_type, payload));
9d0ec61c70a1 mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents: 4888
diff changeset
396 if not ret then return err; end
4514
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
397 response.headers.content_type = send_type;
4917
9d0ec61c70a1 mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents: 4888
diff changeset
398 return ret;
4514
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
399 end
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
400
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
401 if payload.name == "iq" then
4699
a8af632daf48 mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents: 4532
diff changeset
402 local responses = st.stanza("xmpp");
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
403 function origin.send(stanza)
4699
a8af632daf48 mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents: 4532
diff changeset
404 responses:add_direct_child(stanza);
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
405 end
4735
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
406 if compat_preevents(origin, payload) then return 202; end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
407
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
408 if payload.attr.type ~= "get" and payload.attr.type ~= "set" then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
409 return post_errors.new("iq_type");
3832
0d4146cf9fbc mod_rest: Enforce single child policy for outgoing it stanzas
Kim Alvefur <zash@zash.se>
parents: 3825
diff changeset
410 elseif #payload.tags ~= 1 then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
411 return post_errors.new("iq_tags");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
412 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
413
4941
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
414 -- special handling of multiple responses to MAM queries primarily from
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
415 -- remote hosts, local go directly to origin.send()
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
416 local archive_event_name = "message"..event_suffix(from);
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
417 local archive_handler;
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
418 local archive_query = payload:get_child("query", "urn:xmpp:mam:2");
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
419 if archive_query then
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
420 archive_handler = function(result_event)
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
421 if result_event.stanza:find("{urn:xmpp:mam:2}result/@queryid") == archive_query.attr.queryid then
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
422 origin.send(result_event.stanza);
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
423 return true;
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
424 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
425 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
426 module:hook(archive_event_name, archive_handler, 1);
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
427 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
428
5332
e0b5468aae49 mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents: 5087
diff changeset
429 local iq_timeout = tonumber(request.headers.prosody_rest_timeout) or module:get_option_number("rest_iq_timeout", 60*2);
5334
3c51eab0afe8 mod_rest: Get correct type from config
Kim Alvefur <zash@zash.se>
parents: 5332
diff changeset
430 iq_timeout = math.min(iq_timeout, module:get_option_number("rest_iq_max_timeout", 300));
5332
e0b5468aae49 mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents: 5087
diff changeset
431
e0b5468aae49 mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents: 5087
diff changeset
432 local p = module:send_iq(payload, origin, iq_timeout):next(
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
433 function (result)
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
434 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
435 response.headers.content_type = send_type;
4943
e67cc71727ca mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents: 4942
diff changeset
436 if responses[1] then
e67cc71727ca mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents: 4942
diff changeset
437 local tail = responses[#responses];
e67cc71727ca mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents: 4942
diff changeset
438 if tail.name ~= "iq" or tail.attr.from ~= result.stanza.attr.from or tail.attr.id ~= result.stanza.attr.id then
e67cc71727ca mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents: 4942
diff changeset
439 origin.send(result.stanza);
e67cc71727ca mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents: 4942
diff changeset
440 end
4942
83a54f4af94c mod_rest: Ensure MAM result-iq is included in results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4941
diff changeset
441 end
4699
a8af632daf48 mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents: 4532
diff changeset
442 if responses[2] then
a8af632daf48 mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents: 4532
diff changeset
443 return encode(send_type, responses);
a8af632daf48 mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents: 4532
diff changeset
444 end
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
445 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
446 end,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
447 function (error)
3909
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
448 if not errors.is_err(error) then
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
449 log("error", "Uncaught native error: %s", error);
3909
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
450 return select(2, errors.coerce(nil, error));
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
451 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
452 response.headers.content_type = send_type;
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
453 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
454 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
455 else
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
456 return error;
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
457 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
458 end);
4941
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
459
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
460 if archive_handler then
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
461 p:finally(function ()
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
462 module:unhook(archive_event_name, archive_handler);
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
463 end)
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
464 end
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
465
e7b9bc629ecc mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents: 4922
diff changeset
466 return p;
3805
683b06c0348f mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents: 3804
diff changeset
467 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
468 function origin.send(stanza)
5585
5b316088bef5 mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents: 5557
diff changeset
469 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
470 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
471 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
472 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
473 end
4735
58a20d5ac6e9 mod_rest: Fire pre-events
Kim Alvefur <zash@zash.se>
parents: 4734
diff changeset
474 if compat_preevents(origin, payload) then return 202; end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
475
3814
0dede5b0ab27 mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents: 3813
diff changeset
476 module:send(payload, origin);
0dede5b0ab27 mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents: 3813
diff changeset
477 return 202;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
478 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
479 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
480
4888
dc7c9ae15f43 mod_rest: Ensure mod_http is loaded before API demo
Kim Alvefur <zash@zash.se>
parents: 4841
diff changeset
481 module:depends("http");
dc7c9ae15f43 mod_rest: Ensure mod_http is loaded before API demo
Kim Alvefur <zash@zash.se>
parents: 4841
diff changeset
482
4488
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
483 local demo_handlers = {};
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
484 if module:get_option_path("rest_demo_resources", nil) then
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
485 demo_handlers = module:require"apidemo";
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
486 end
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
487
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
488 -- Handle stanzas submitted via HTTP
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
489 module:provides("http", {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
490 route = {
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
491 POST = handle_request;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
492 ["POST /*"] = handle_request;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
493 ["GET /*"] = handle_request;
4488
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
494
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
495 -- Only if api_demo_resources are set
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
496 ["GET /"] = demo_handlers.redirect;
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
497 ["GET /demo/"] = demo_handlers.main_page;
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
498 ["GET /demo/openapi.yaml"] = demo_handlers.schema;
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
499 ["GET /demo/*"] = demo_handlers.resources;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
500 };
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
501 });
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
502
5087
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
503 function new_webhook(rest_url, send_type)
4920
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
504 local function get_url() return rest_url; end
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
505 if rest_url:find("%b{}") then
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
506 local httputil = require "util.http";
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
507 local render_url = require"util.interpolation".new("%b{}", httputil.urlencode);
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
508 function get_url(stanza)
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
509 local at = stanza.attr;
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
510 return render_url(rest_url, { kind = stanza.name, type = at.type, to = at.to, from = at.from });
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
511 end
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
512 end
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
513 if send_type == "json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
514 send_type = "application/json";
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
515 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
516
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
517 module:set_status("info", "Not yet connected");
4920
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
518 http.request(get_url(st.stanza("meta", { type = "info", to = module.host, from = module.host })), {
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
519 method = "OPTIONS",
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
520 }, function (body, code, response)
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
521 if code == 0 then
4921
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
522 module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, body);
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
523 elseif code == 200 then
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
524 module:set_status("info", "Connected");
4921
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
525 if response.headers.accept then
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
526 send_type = decide_type(response.headers.accept, supported_outputs);
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
527 module:log("debug", "Set 'rest_callback_content_type' = %q based on Accept header", send_type);
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
528 end
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
529 else
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
530 module:log_status("warn", "Unexpected response code %d from OPTIONS probe", code);
816b23e09c20 mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents: 4920
diff changeset
531 module:log("warn", "Endpoint said: %s", body);
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
532 end
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
533 end);
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
534
4245
7bf3bf81c9ef mod_rest: Use HTTP error mapping from net.http.errors
Kim Alvefur <zash@zash.se>
parents: 4244
diff changeset
535 local code2err = require "net.http.errors".registry;
3797
ed5d7586a61e mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents: 3796
diff changeset
536
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
537 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
538 local stanza, origin = event.stanza, event.origin;
5086
dec4b2e31d1c mod_rest: Do not allow replies to <iq type=result> from webhooks
Kim Alvefur <zash@zash.se>
parents: 5001
diff changeset
539 local reply_allowed = stanza.attr.type ~= "error" and stanza.attr.type ~= "result";
4250
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
540 local reply_needed = reply_allowed and stanza.name == "iq";
3798
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
541 local receipt;
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
542
4250
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
543 if reply_allowed and stanza.name == "message" and stanza.attr.id and stanza:get_child("urn:xmpp:receipts", "request") then
3798
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
544 reply_needed = true;
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
545 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
546 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
547
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
548 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
549
a1f1f703d604 mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents: 3798
diff changeset
550 -- 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
551 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
552
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
553 module:log("debug", "Sending[rest]: %s", stanza:top_tag());
4920
bdac7c717c91 mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents: 4918
diff changeset
554 http.request(get_url(stanza), {
3799
a1f1f703d604 mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents: 3798
diff changeset
555 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
556 headers = {
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
557 ["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
558 ["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
559 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
560 },
4247
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
561 }):next(function (response)
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
562 module:set_status("info", "Connected");
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
563 local reply;
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
564
4247
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
565 local code, body = response.code, response.body;
4250
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
566 if not reply_allowed then
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
567 return;
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
568 elseif code == 202 or code == 204 then
3867
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
569 if not reply_needed then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
570 -- Delivered, no reply
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
571 return;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
572 end
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
573 else
3867
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
574 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
575 if not parsed then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
576 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
577 elseif parsed.name ~= stanza.name then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
578 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
579 else
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
580 parsed.attr = {
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
581 from = stanza.attr.to,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
582 to = stanza.attr.from,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
583 id = parsed.attr.id or id.medium();
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
584 type = parsed.attr.type,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
585 ["xml:lang"] = parsed.attr["xml:lang"],
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
586 };
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
587 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
588 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
589 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
590 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
591 parsed.attr.type = "error";
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
592 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
593 if parsed.attr.type == "error" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
594 parsed.attr.id = stanza.attr.id;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
595 elseif parsed.name == "iq" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
596 parsed.attr.id = stanza.attr.id;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
597 parsed.attr.type = "result";
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
598 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
599 reply = parsed;
3821
11272a3233ce mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents: 3816
diff changeset
600 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
601 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
602
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
603 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
604 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
605 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
606 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
607 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
608 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
609 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
610 -- 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
611 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
612 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
613 elseif code_hundreds == 400 then
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
614 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
615 elseif code_hundreds == 500 then
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
616 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
617 else
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
618 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
619 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
620 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
621
3798
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
622 if receipt then
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
623 reply:add_direct_child(receipt);
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
624 end
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
625
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
626 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
627
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
628 origin.send(reply);
4247
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
629 end,
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
630 function (err)
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
631 module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, err);
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
632 origin.send(st.error_reply(stanza, "wait", "recipient-unavailable", err.text));
4249
64aa1d9d70ac mod_rest: Catch and log errors in callback promise chain
Kim Alvefur <zash@zash.se>
parents: 4247
diff changeset
633 end):catch(function (err)
64aa1d9d70ac mod_rest: Catch and log errors in callback promise chain
Kim Alvefur <zash@zash.se>
parents: 4247
diff changeset
634 module:log("error", "Error[rest]: %s", err);
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
635 end);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
636
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
637 return true;
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
638 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
639
5087
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
640 return handle_stanza;
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
641 end
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
642
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
643 -- Forward stanzas from XMPP to HTTP and return any reply
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
644 local rest_url = module:get_option_string("rest_callback_url", nil);
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
645 if rest_url then
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
646 local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml");
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
647
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
648 local handle_stanza = new_webhook(rest_url, send_type);
438fbebf74ac mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents: 5086
diff changeset
649
4922
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
650 local send_kinds = module:get_option_set("rest_callback_stanzas", { "message", "presence", "iq" });
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
651
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
652 local event_presets = {
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
653 -- Don't override everything on normal VirtualHosts by default
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
654 ["local"] = { "host" },
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
655 -- Comonents get to handle all kinds of stanzas
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
656 ["component"] = { "bare", "full", "host" },
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
657 };
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
658 local hook_events = module:get_option_set("rest_callback_events", event_presets[module:get_host_type()]);
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
659 for kind in send_kinds do
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
660 for event in hook_events do
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
661 module:hook(kind.."/"..event, handle_stanza, -1);
c83b009b5bc5 mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents: 4921
diff changeset
662 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
663 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
664 end
3842
501c7edc8c37 mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents: 3832
diff changeset
665
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
666 local supported_errors = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
667 "text/html",
3931
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
668 "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
669 "application/json",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
670 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
671
6206
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
672 -- strip some stuff, notably the optional traceback table that casues stack overflow in util.json
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
673 local function simplify_error(e)
6244
c71d8bc77c95 mod_rest: Skip unpacking error object when missing (thanks Martin)
Kim Alvefur <zash@zash.se>
parents: 6206
diff changeset
674 if not e then return end
6206
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
675 return {
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
676 type = e.type;
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
677 condition = e.condition;
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
678 text = e.text;
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
679 extra = e.extra;
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
680 source = e.source;
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
681 };
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
682 end
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
683
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
684 local http_server = require "net.http.server";
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
685 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
686 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
687 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
688 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
689 if response then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
690 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
691 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
692 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
693 if event.error then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
694 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
695 if event.error.text then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
696 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
697 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
698 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
699 return tostring(stream_error);
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
700 elseif response_as == "application/json" then
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
701 if response then
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
702 response.headers.content_type = "application/json";
3842
501c7edc8c37 mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents: 3832
diff changeset
703 end
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
704 return json.encode({
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
705 type = "error",
6206
ac7e2992fe6e mod_rest: Strip down error payloads to avoid stack overflow
Kim Alvefur <zash@zash.se>
parents: 5993
diff changeset
706 error = simplify_error(event.error),
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
707 code = event.code,
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
708 });
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
709 end
3933
93147b89ea67 mod_rest: Avoid interfering with mod_http_oauth2 errors (fixes #1500)
Kim Alvefur <zash@zash.se>
parents: 3931
diff changeset
710 end, 1);