annotate mod_rest/mod_rest.lua @ 4515:2e33eeafe962

mod_muc_markers: Prevent any markers from reaching the archive, even if untracked Original intention was to leave alone things that this module isn't handling. However markers in archives are just problematic without more advanced logic about what is markable and what is not. It also requires a more advanced query in mod_muc_rai to determine the latest markable message instead of the latest archived message. I'd rather keep the "is archivable" and "is markable" definition the same for simplicity. I don't want to introduce yet another set of rules for no reason. No markers in MAM.
author Matthew Wild <mwild1@gmail.com>
date Mon, 22 Mar 2021 15:55:02 +0000
parents 81d0748bff5b
children 23b681214be3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
1 -- RESTful API
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
2 --
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
3 -- Copyright (c) 2019-2020 Kim Alvefur
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
4 --
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
5 -- This file is MIT/X11 licensed.
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
6
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
7 local encodings = require "util.encodings";
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
8 local base64 = encodings.base64;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
9 local errors = require "util.error";
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
10 local http = require "net.http";
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
11 local id = require "util.id";
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
12 local jid = require "util.jid";
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
13 local json = require "util.json";
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
14 local st = require "util.stanza";
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
15 local um = require "core.usermanager";
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
16 local xml = require "util.xml";
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
17 local have_cbor, cbor = pcall(require, "cbor");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
18
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
19 local jsonmap = module:require"jsonmap";
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
20
3915
80dffbbd056b mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents: 3911
diff changeset
21 local tokens = module:depends("tokenauth");
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
22
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
23 local auth_mechanisms = module:get_option_set("rest_auth_mechanisms", { "Basic", "Bearer" });
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
24
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
25 local www_authenticate_header;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
26 do
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
27 local header, realm = {}, module.host.."/"..module.name;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
28 for mech in auth_mechanisms do
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
29 header[#header+1] = ("%s realm=%q"):format(mech, realm);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
30 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
31 www_authenticate_header = table.concat(header, ", ");
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
32 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
33
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
34 -- Bearer token
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
35 local function check_credentials(request)
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
36 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$");
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
37 if not (auth_type and auth_data) or not auth_mechanisms:contains(auth_type) then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
38 return false;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
39 end
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
40
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
41 if auth_type == "Basic" then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
42 local creds = base64.decode(auth_data);
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
43 if not creds then return false; end
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
44 local username, password = string.match(creds, "^([^:]+):(.*)$");
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
45 if not username then return false; end
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
46 username, password = encodings.stringprep.nodeprep(username), encodings.stringprep.saslprep(password);
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
47 if not username then return false; end
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
48 if not um.test_password(username, module.host, password) then
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
49 return false;
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
50 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
51 return { username = username, host = module.host };
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
52 elseif auth_type == "Bearer" then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
53 local token_info = tokens.get_token_info(auth_data);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
54 if not token_info or not token_info.session then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
55 return false;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
56 end
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
57 return token_info.session;
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
58 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
59 return nil;
3876
75b330d4fa6f mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents: 3874
diff changeset
60 end
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
61
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
62 -- (table, string) -> table
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
63 local function amend_from_path(data, path)
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
64 local st_kind, st_type, st_to = path:match("^([mpi]%w+)/(%w+)/(.*)$");
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
65 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
66 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
67 -- 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
68 data = {
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
69 kind = "iq";
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
70 type = "get";
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
71 [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
72 };
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
73 else
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
74 data.kind = st_kind;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
75 data.type = st_type;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
76 end
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
77 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
78 data.to = st_to;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
79 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
80 return data;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
81 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
82
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
83 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
84 mimetype = mimetype and mimetype:match("^[^; ]*");
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
85 if mimetype == "application/xmpp+xml" then
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
86 return xml.parse(data);
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
87 elseif mimetype == "application/json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
88 local parsed, err = json.decode(data);
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
89 if not parsed then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
90 return parsed, err;
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
91 end
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
92 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
93 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
94 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
95 end
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
96 return jsonmap.json2st(parsed);
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
97 elseif mimetype == "application/cbor" and have_cbor then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
98 local parsed, err = cbor.decode(data);
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
99 if not parsed then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
100 return parsed, err;
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
101 end
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
102 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
103 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
104 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
105 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
106 -- 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
107 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
108 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
109 end
3911
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
110 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
111 end
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
112 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
113 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
114 end
4503
80912726405d mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents: 4502
diff changeset
115 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
116 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
117 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
118 end
3911
064c32a5be7c mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents: 3910
diff changeset
119 return jsonmap.json2st(parsed);
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
120 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
121 if not path then
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
122 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
123 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
124 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
125 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
126 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
127 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
128 end
4477
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
129 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
130 parsed.body = data;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
131 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
132 parsed.show = data;
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
133 else
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
134 return nil, "invalid-path";
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
135 end
8df6cc648963 mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents: 4250
diff changeset
136 return jsonmap.json2st(parsed);
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
137 elseif not mimetype and path then
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
138 local parsed = amend_from_path({}, path);
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
139 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
140 return jsonmap.json2st(parsed);
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
141 end
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
142 return nil, "unknown-payload-type";
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
143 end
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
144
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
145 local function decide_type(accept, supported_types)
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
146 -- assumes the accept header is sorted
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
147 local ret = supported_types[1];
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
148 for i = 2, #supported_types do
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
149 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
150 ret = supported_types[i];
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
151 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
152 end
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
153 return ret;
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
154 end
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
155
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
156 local supported_inputs = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
157 "application/xmpp+xml",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
158 "application/json",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
159 "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
160 "text/plain",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
161 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
162
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
163 local supported_outputs = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
164 "application/xmpp+xml",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
165 "application/json",
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
166 "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
167 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
168
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
169 if have_cbor then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
170 table.insert(supported_inputs, "application/cbor");
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
171 table.insert(supported_outputs, "application/cbor");
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
172 end
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
173
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
174 -- 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
175 -- (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
176 local function flatten(t)
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
177 local form = {};
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
178 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
179 if type(v) == "string" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
180 form[k] = v;
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
181 elseif type(v) == "number" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
182 form[k] = tostring(v);
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
183 elseif v == true then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
184 form[k] = "";
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
185 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
186 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
187 return form;
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
188 end
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
189
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
190 local function encode(type, s)
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
191 if type == "application/json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
192 return json.encode(jsonmap.st2json(s));
4066
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
193 elseif type == "application/x-www-form-urlencoded" then
07ae583bc565 mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents: 4037
diff changeset
194 return http.formencode(flatten(jsonmap.st2json(s)));
4037
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
195 elseif type == "application/cbor" then
991090cb5d18 mod_rest: Add support for CBOR
Kim Alvefur <zash@zash.se>
parents: 4036
diff changeset
196 return cbor.encode(jsonmap.st2json(s));
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
197 elseif type == "text/plain" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
198 return s:get_child_text("body") or "";
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
199 end
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
200 return tostring(s);
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
201 end
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
202
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
203 local post_errors = errors.init("mod_rest", {
3971
ae5ac41c391d mod_rest: Improve auth error reporting
Kim Alvefur <zash@zash.se>
parents: 3933
diff changeset
204 noauthz = { code = 401, type = "auth", condition = "not-authorized", text = "No credentials provided" },
ae5ac41c391d mod_rest: Improve auth error reporting
Kim Alvefur <zash@zash.se>
parents: 3933
diff changeset
205 unauthz = { code = 403, type = "auth", condition = "not-authorized", text = "Credentials not accepted" },
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
206 parse = { code = 400, condition = "not-well-formed", text = "Failed to parse payload", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
207 xmlns = { code = 422, condition = "invalid-namespace", text = "'xmlns' attribute must be empty", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
208 name = { code = 422, condition = "unsupported-stanza-type", text = "Invalid stanza, must be 'message', 'presence' or 'iq'.", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
209 to = { code = 422, condition = "improper-addressing", text = "Invalid destination JID", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
210 from = { code = 422, condition = "invalid-from", text = "Invalid source JID", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
211 post_auth = { code = 403, condition = "not-authorized", text = "Not authorized to send stanza with requested 'from'", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
212 iq_type = { code = 422, condition = "invalid-xml", text = "'iq' stanza must be of type 'get' or 'set'", },
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
213 iq_tags = { code = 422, condition = "bad-format", text = "'iq' stanza must have exactly one child tag", },
4036
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
214 mediatype = { code = 415, condition = "bad-format", text = "Unsupported media type" },
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
215 });
3930
d5dafd617cd6 mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents: 3929
diff changeset
216
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
217 -- GET → iq-get
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
218 local function parse_request(request, path)
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
219 if path and request.method == "GET" then
4506
508cb880b163 mod_rest: Fix typos [codespell]
Kim Alvefur <zash@zash.se>
parents: 4503
diff changeset
220 -- 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
221 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
222 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
223 end
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
224 return parse(nil, nil, "iq/"..path);
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
225 else
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
226 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
227 end
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
228 end
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
229
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
230 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
231 local request, response = event.request, event.response;
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
232 local from;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
233 local origin;
4514
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
234 local echo = path == "echo";
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
235 if echo then path = nil; end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
236
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
237 if not request.headers.authorization then
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
238 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
239 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
240 else
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
241 origin = check_credentials(request);
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
242 if not origin then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
243 return 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
244 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
245 from = jid.join(origin.username, origin.host, origin.resource);
3802
f88e07630e4e mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents: 3801
diff changeset
246 end
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
247 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
248 if not payload then
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
249 -- parse fail
4036
04c11b652aeb mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents: 3971
diff changeset
250 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
251 if err == "unknown-payload-type" then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
252 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
253 end
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
254 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
255 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
256
3801
d59fb4dcf100 mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents: 3799
diff changeset
257 if payload.attr.xmlns then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
258 return post_errors.new("xmlns");
3805
683b06c0348f mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents: 3804
diff changeset
259 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
260 return post_errors.new("name");
3801
d59fb4dcf100 mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents: 3799
diff changeset
261 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
262
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
263 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
264 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
265 return post_errors.new("to");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
266 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
267
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
268 if payload.attr.from then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
269 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
270 if not requested_from then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
271 return post_errors.new("from");
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
272 end
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
273 if jid.compare(requested_from, from) then
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
274 from = requested_from;
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
275 else
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
276 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
277 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
278 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
279
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
280 payload.attr = {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
281 from = from,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
282 to = to,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
283 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
284 type = payload.attr.type,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
285 ["xml:lang"] = payload.attr["xml:lang"],
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
286 };
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
287
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
288 module: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
289 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
290
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
291 if echo then
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
292 response.headers.content_type = send_type;
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
293 return encode(send_type, payload);
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
294 end
81d0748bff5b mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents: 4506
diff changeset
295
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
296 if payload.name == "iq" then
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
297 function origin.send(stanza)
3926
f77ae9685eb6 mod_rest: Fix routing to self-jid (thanks jonas’)
Kim Alvefur <zash@zash.se>
parents: 3925
diff changeset
298 module:send(stanza);
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
299 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
300
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
301 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
302 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
303 elseif #payload.tags ~= 1 then
4244
07c11080027e mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents: 4242
diff changeset
304 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
305 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
306
3910
49efd1323a1b mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents: 3909
diff changeset
307 return module:send_iq(payload, origin):next(
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
308 function (result)
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
309 module:log("debug", "Sending[rest]: %s", result.stanza:top_tag());
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
310 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
311 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
312 end,
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
313 function (error)
3909
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
314 if not errors.is_err(error) then
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
315 module:log("error", "Uncaught native error: %s", error);
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
316 return select(2, errors.coerce(nil, error));
eb27e51cf2c9 mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents: 3887
diff changeset
317 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
318 response.headers.content_type = send_type;
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
319 module:log("debug", "Sending[rest]: %s", error.context.stanza:top_tag());
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
320 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
321 else
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
322 return error;
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
323 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
324 end);
3805
683b06c0348f mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents: 3804
diff changeset
325 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
326 function origin.send(stanza)
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
327 module:log("debug", "Sending[rest]: %s", stanza:top_tag());
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
328 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
329 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
330 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
331 end
4242
6a91d217acc9 mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents: 4066
diff changeset
332
3814
0dede5b0ab27 mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents: 3813
diff changeset
333 module:send(payload, origin);
0dede5b0ab27 mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents: 3813
diff changeset
334 return 202;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
335 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
336 end
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
337
4488
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
338 local demo_handlers = {};
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
339 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
340 demo_handlers = module:require"apidemo";
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
341 end
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
342
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
343 -- Handle stanzas submitted via HTTP
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
344 module:depends("http");
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
345 module:provides("http", {
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
346 route = {
4478
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
347 POST = handle_request;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
348 ["POST /*"] = handle_request;
7ab0c423688a mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents: 4477
diff changeset
349 ["GET /*"] = handle_request;
4488
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
350
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
351 -- 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
352 ["GET /"] = demo_handlers.redirect;
eea62d30ae08 mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents: 4481
diff changeset
353 ["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
354 ["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
355 ["GET /demo/*"] = demo_handlers.resources;
3794
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
356 };
4b258329e6e4 mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
357 });
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
358
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
359 -- Forward stanzas from XMPP to HTTP and return any reply
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
360 local rest_url = module:get_option_string("rest_callback_url", nil);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
361 if rest_url then
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
362 local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml");
3813
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
363 if send_type == "json" then
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
364 send_type = "application/json";
aa1ad69c7c10 mod_rest: Add JSON support
Kim Alvefur <zash@zash.se>
parents: 3812
diff changeset
365 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
366
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
367 module:set_status("info", "Not yet connected");
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
368 http.request(rest_url, {
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
369 method = "OPTIONS",
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
370 }, function (body, code, response)
3862
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
371 if code == 0 then
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
372 return module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, body);
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
373 else
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
374 module:set_status("info", "Connected");
3b6b8dcff78e mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents: 3861
diff changeset
375 end
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
376 if code == 200 and response.headers.accept then
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
377 send_type = decide_type(response.headers.accept, supported_outputs);
3861
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
378 module:log("debug", "Set 'rest_callback_content_type' = %q based on Accept header", send_type);
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
379 end
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
380 end);
ede3d1724dd1 mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents: 3858
diff changeset
381
4245
7bf3bf81c9ef mod_rest: Use HTTP error mapping from net.http.errors
Kim Alvefur <zash@zash.se>
parents: 4244
diff changeset
382 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
383
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
384 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
385 local stanza, origin = event.stanza, event.origin;
4250
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
386 local reply_allowed = stanza.attr.type ~= "error";
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
387 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
388 local receipt;
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
389
4250
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
390 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
391 reply_needed = true;
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
392 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
393 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
394
3812
f027b8b1e794 mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents: 3811
diff changeset
395 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
396
a1f1f703d604 mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents: 3798
diff changeset
397 -- 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
398 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
399
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
400 module:log("debug", "Sending[rest]: %s", stanza:top_tag());
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
401 http.request(rest_url, {
3799
a1f1f703d604 mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents: 3798
diff changeset
402 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
403 headers = {
3811
eb25110696cd mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents: 3810
diff changeset
404 ["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
405 ["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
406 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
407 },
4247
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
408 }):next(function (response)
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
409 module:set_status("info", "Connected");
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
410 local reply;
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
411
4247
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
412 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
413 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
414 return;
8b489203e4d3 mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents: 4249
diff changeset
415 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
416 if not reply_needed then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
417 -- Delivered, no reply
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
418 return;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
419 end
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
420 else
3867
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
421 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
422 if not parsed then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
423 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
424 elseif parsed.name ~= stanza.name then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
425 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
426 else
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
427 parsed.attr = {
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
428 from = stanza.attr.to,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
429 to = stanza.attr.from,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
430 id = parsed.attr.id or id.medium();
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
431 type = parsed.attr.type,
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
432 ["xml:lang"] = parsed.attr["xml:lang"],
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
433 };
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
434 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
435 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
436 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
437 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
438 parsed.attr.type = "error";
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
439 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
440 if parsed.attr.type == "error" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
441 parsed.attr.id = stanza.attr.id;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
442 elseif parsed.name == "iq" then
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
443 parsed.attr.id = stanza.attr.id;
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
444 parsed.attr.type = "result";
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
445 end
839224be5299 mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents: 3866
diff changeset
446 reply = parsed;
3821
11272a3233ce mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents: 3816
diff changeset
447 end
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
448 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
449
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
450 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
451 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
452 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
453 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
454 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
455 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
456 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
457 -- 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
458 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
459 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
460 elseif code_hundreds == 400 then
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
461 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
462 elseif code_hundreds == 500 then
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
463 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
464 else
3810
91ff86fc3b20 mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents: 3807
diff changeset
465 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
466 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
467 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
468
3798
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
469 if receipt then
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
470 reply:add_direct_child(receipt);
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
471 end
9b4fd2553365 mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents: 3797
diff changeset
472
3803
dc2b5a412286 mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents: 3802
diff changeset
473 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
474
3795
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
475 origin.send(reply);
4247
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
476 end,
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
477 function (err)
1f93fa24611d mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents: 4245
diff changeset
478 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
479 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
480 end):catch(function (err)
64aa1d9d70ac mod_rest: Catch and log errors in callback promise chain
Kim Alvefur <zash@zash.se>
parents: 4247
diff changeset
481 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
482 end);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
483
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
484 return true;
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
485 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
486
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
487 if module:get_host_type() == "component" then
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
488 module:hook("iq/bare", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
489 module:hook("message/bare", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
490 module:hook("presence/bare", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
491 module:hook("iq/full", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
492 module:hook("message/full", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
493 module:hook("presence/full", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
494 module:hook("iq/host", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
495 module:hook("message/host", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
496 module:hook("presence/host", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
497 else
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
498 -- Don't override everything on normal VirtualHosts
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
499 module:hook("iq/host", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
500 module:hook("message/host", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
501 module:hook("presence/host", handle_stanza, -1);
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
502 end
f51308fcba83 mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents: 3794
diff changeset
503 end
3842
501c7edc8c37 mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents: 3832
diff changeset
504
3929
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
505 local supported_errors = {
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
506 "text/html",
3931
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
507 "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
508 "application/json",
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
509 };
bd687d586a8a mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents: 3926
diff changeset
510
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
511 local http_server = require "net.http.server";
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
512 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
513 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
514 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
515 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
516 if response then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
517 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
518 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
519 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
520 if event.error then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
521 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
522 if event.error.text then
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
523 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
524 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
525 end
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
526 return tostring(stream_error);
2e8b284ac8b3 mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents: 3930
diff changeset
527 elseif response_as == "application/json" then
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
528 if response then
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
529 response.headers.content_type = "application/json";
3842
501c7edc8c37 mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents: 3832
diff changeset
530 end
3873
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
531 return json.encode({
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
532 type = "error",
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
533 error = event.error,
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
534 code = event.code,
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
535 });
fea0c1bed1a0 mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents: 3872
diff changeset
536 end
3933
93147b89ea67 mod_rest: Avoid interfering with mod_http_oauth2 errors (fixes #1500)
Kim Alvefur <zash@zash.se>
parents: 3931
diff changeset
537 end, 1);