Mercurial > prosody-modules
annotate mod_rest/mod_rest.lua @ 5696:66986f5271c3
mod_storage_s3: Skip archive items matching on date but not full datetime
Since it only encodes dates in paths, it would have returned items from
outside the specified start..end range if they were from earlier or
later in the same (UTC) day.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 11 Nov 2023 22:26:39 +0100 |
parents | 0cffeff2cd1d |
children | 32d1abb89dfe |
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 -- |
4921
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
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 | 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 | 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 |
5678
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 |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
26 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
|
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 |
3802
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
37 local function check_credentials(request) |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
38 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
|
39 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
|
40 return false; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
41 end |
3876
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3874
diff
changeset
|
42 |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
43 if auth_type == "Basic" then |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
44 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
|
45 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
|
46 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
|
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 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
|
49 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
|
50 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
|
51 return false; |
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3874
diff
changeset
|
52 end |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
53 return { username = username, host = module.host }; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
54 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
|
55 if tokens.get_token_session then |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4988
diff
changeset
|
56 return tokens.get_token_session(auth_data); |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4988
diff
changeset
|
57 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
|
58 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
|
59 if not token_info or not token_info.session then |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4988
diff
changeset
|
60 return false; |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4988
diff
changeset
|
61 end |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4988
diff
changeset
|
62 return token_info.session; |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
63 end |
3876
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3874
diff
changeset
|
64 end |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
65 return nil; |
3876
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3874
diff
changeset
|
66 end |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
67 |
4734
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
68 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
|
69 www_authenticate_header = nil; |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
70 function check_credentials(request) -- luacheck: ignore 212/request |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
71 return { |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
72 username = id.medium():lower(); |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
73 host = module.host; |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
74 } |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
75 end |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
76 end |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
77 |
4942
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
78 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:
4923
diff
changeset
|
79 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:
4923
diff
changeset
|
80 if node then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
81 if resource then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
82 return '/full'; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
83 else |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
84 return '/bare'; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
85 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
86 else |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
87 return '/host'; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
88 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
89 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
90 |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
91 |
4735 | 92 -- TODO This ought to be handled some way other than duplicating this |
93 -- core.stanza_router code here. | |
94 local function compat_preevents(origin, stanza) --> boolean : handled | |
95 local to = stanza.attr.to; | |
96 local node, host, resource = jid.split(to); | |
97 | |
98 local to_type, to_self; | |
99 if node then | |
100 if resource then | |
101 to_type = '/full'; | |
102 else | |
103 to_type = '/bare'; | |
104 if node == origin.username and host == origin.host then | |
105 stanza.attr.to = nil; | |
106 to_self = true; | |
107 end | |
108 end | |
109 else | |
110 if host then | |
111 to_type = '/host'; | |
112 else | |
113 to_type = '/bare'; | |
114 to_self = true; | |
115 end | |
116 end | |
117 | |
118 local event_data = { origin = origin; stanza = stanza; to_self = to_self }; | |
119 | |
120 local result = module:fire_event("pre-stanza", event_data); | |
121 if result ~= nil then return true end | |
122 if module:fire_event('pre-' .. stanza.name .. to_type, event_data) then return true; end -- do preprocessing | |
123 return false | |
124 end | |
125 | |
4477
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
126 -- (table, string) -> table |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
127 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
|
128 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
|
129 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
|
130 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
|
131 -- 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
|
132 data = { |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4502
diff
changeset
|
133 kind = "iq"; |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4502
diff
changeset
|
134 [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
|
135 }; |
4478
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
136 else |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
137 data.kind = st_kind; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
138 data.type = st_type; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
139 end |
4477
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
140 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
|
141 data.to = st_to; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
142 end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
143 return data; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
144 end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
145 |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
146 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
|
147 mimetype = mimetype and mimetype:match("^[^; ]*"); |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
148 if mimetype == "application/xmpp+xml" then |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
149 return xml.parse(data); |
3813 | 150 elseif mimetype == "application/json" then |
151 local parsed, err = json.decode(data); | |
152 if not parsed then | |
153 return parsed, err; | |
154 end | |
4503
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4502
diff
changeset
|
155 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
|
156 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
|
157 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
|
158 end |
3813 | 159 return jsonmap.json2st(parsed); |
4037 | 160 elseif mimetype == "application/cbor" and have_cbor then |
161 local parsed, err = cbor.decode(data); | |
162 if not parsed then | |
163 return parsed, err; | |
164 end | |
165 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
|
166 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
|
167 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
|
168 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
|
169 -- 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
|
170 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
|
171 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
|
172 end |
3911
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3910
diff
changeset
|
173 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
|
174 end |
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3910
diff
changeset
|
175 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
|
176 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
|
177 end |
4503
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4502
diff
changeset
|
178 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
|
179 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
|
180 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
|
181 end |
3911
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3910
diff
changeset
|
182 return jsonmap.json2st(parsed); |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
183 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
|
184 if not path then |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
185 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
|
186 end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
187 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
|
188 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
|
189 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
|
190 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
|
191 end |
4477
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
192 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
|
193 parsed.body = data; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
194 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
|
195 parsed.show = data; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
196 else |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
197 return nil, "invalid-path"; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
198 end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4250
diff
changeset
|
199 return jsonmap.json2st(parsed); |
4478
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
200 elseif not mimetype and path then |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
201 local parsed = amend_from_path({}, path); |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
202 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
|
203 return jsonmap.json2st(parsed); |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
204 end |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
205 return nil, "unknown-payload-type"; |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
206 end |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
207 |
3929
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
208 local function decide_type(accept, supported_types) |
3813 | 209 -- assumes the accept header is sorted |
210 local ret = supported_types[1]; | |
211 for i = 2, #supported_types do | |
212 if (accept:find(supported_types[i], 1, true) or 1000) < (accept:find(ret, 1, true) or 1000) then | |
213 ret = supported_types[i]; | |
214 end | |
215 end | |
216 return ret; | |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
217 end |
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
218 |
3929
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
219 local supported_inputs = { |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
220 "application/xmpp+xml", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
221 "application/json", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
222 "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
|
223 "text/plain", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
224 }; |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
225 |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
226 local supported_outputs = { |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
227 "application/xmpp+xml", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
228 "application/json", |
4066
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
229 "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
|
230 }; |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
231 |
4037 | 232 if have_cbor then |
233 table.insert(supported_inputs, "application/cbor"); | |
234 table.insert(supported_outputs, "application/cbor"); | |
235 end | |
236 | |
4066
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
237 -- 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
|
238 -- (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
|
239 local function flatten(t) |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
240 local form = {}; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
241 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
|
242 if type(v) == "string" then |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
243 form[k] = v; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
244 elseif type(v) == "number" then |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
245 form[k] = tostring(v); |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
246 elseif v == true then |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
247 form[k] = ""; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
248 end |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
249 end |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
250 return form; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
251 end |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
252 |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
253 local function encode(type, s) |
4919
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
254 if type == "text/plain" then |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
255 return s:get_child_text("body") or ""; |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
256 elseif type == "application/xmpp+xml" then |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
257 return tostring(s); |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
258 end |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
259 local mapped, err = jsonmap.st2json(s); |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
260 if not mapped then return mapped, err; end |
3813 | 261 if type == "application/json" then |
4919
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
262 return json.encode(mapped); |
4066
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4037
diff
changeset
|
263 elseif type == "application/x-www-form-urlencoded" then |
4919
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
264 return http.formencode(flatten(mapped)); |
4037 | 265 elseif type == "application/cbor" then |
4919
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
266 return cbor.encode(mapped); |
3813 | 267 end |
4919
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4918
diff
changeset
|
268 error "unsupported encoding"; |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
269 end |
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
270 |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
271 local post_errors = errors.init("mod_rest", { |
4988
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
272 noauthz = { code = 401; type = "auth"; condition = "not-authorized"; text = "No credentials provided" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
273 unauthz = { code = 403; type = "auth"; condition = "not-authorized"; text = "Credentials not accepted" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
274 parse = { code = 400; type = "modify"; condition = "not-well-formed"; text = "Failed to parse payload" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
275 xmlns = { code = 422; type = "modify"; condition = "invalid-namespace"; text = "'xmlns' attribute must be empty" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
276 name = { code = 422; type = "modify"; condition = "unsupported-stanza-type"; text = "Invalid stanza, must be 'message', 'presence' or 'iq'." }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
277 to = { code = 422; type = "modify"; condition = "improper-addressing"; text = "Invalid destination JID" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
278 from = { code = 422; type = "modify"; condition = "invalid-from"; text = "Invalid source JID" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
279 from_auth = { code = 403; type = "auth"; condition = "not-authorized"; text = "Not authorized to send stanza with requested 'from'" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
280 iq_type = { code = 422; type = "modify"; condition = "invalid-xml"; text = "'iq' stanza must be of type 'get' or 'set'" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
281 iq_tags = { code = 422; type = "modify"; condition = "bad-format"; text = "'iq' stanza must have exactly one child tag" }; |
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4955
diff
changeset
|
282 mediatype = { code = 415; type = "cancel"; condition = "bad-format"; text = "Unsupported media type" }; |
5678
0cffeff2cd1d
mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents:
5585
diff
changeset
|
283 size = { code = 413; type = "modify"; condition = "resource-constraint", text = "Payload too large" }; |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
284 }); |
3930
d5dafd617cd6
mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents:
3929
diff
changeset
|
285 |
4478
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
286 -- GET → iq-get |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
287 local function parse_request(request, path) |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
288 if path and request.method == "GET" then |
4506
508cb880b163
mod_rest: Fix typos [codespell]
Kim Alvefur <zash@zash.se>
parents:
4503
diff
changeset
|
289 -- 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
|
290 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
|
291 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
|
292 end |
4478
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
293 return parse(nil, nil, "iq/"..path); |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
294 else |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
295 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
|
296 end |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
297 end |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
298 |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
299 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
|
300 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
|
301 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
|
302 local from; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
303 local origin; |
4514
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
304 local echo = path == "echo"; |
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
305 if echo then path = nil; end |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
306 |
4734
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4727
diff
changeset
|
307 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
|
308 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
|
309 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
|
310 else |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
311 origin = check_credentials(request); |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
312 if not origin then |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
313 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
|
314 end |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
315 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
|
316 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
|
317 origin.type = "c2s"; |
5585
5b316088bef5
mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents:
5557
diff
changeset
|
318 origin.log = log; |
3802
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
319 end |
5678
0cffeff2cd1d
mod_rest: Limit payload size (cf stanza size limits)
Kim Alvefur <zash@zash.se>
parents:
5585
diff
changeset
|
320 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
|
321 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
|
322 end |
4478
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
323 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
|
324 if not payload then |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
325 -- parse fail |
4036
04c11b652aeb
mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents:
3971
diff
changeset
|
326 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
|
327 if err == "unknown-payload-type" then |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
328 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
|
329 end |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
330 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
|
331 end |
4242
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4066
diff
changeset
|
332 |
4841
f69c5a443156
mod_rest: Fix nested message stanzas in XEP-0297 containers
Kim Alvefur <zash@zash.se>
parents:
4745
diff
changeset
|
333 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
|
334 return post_errors.new("xmlns"); |
3805
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3804
diff
changeset
|
335 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
|
336 return post_errors.new("name"); |
3801
d59fb4dcf100
mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents:
3799
diff
changeset
|
337 end |
4242
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4066
diff
changeset
|
338 |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
339 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
|
340 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
|
341 return post_errors.new("to"); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
342 end |
4242
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4066
diff
changeset
|
343 |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
344 if payload.attr.from then |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
345 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
|
346 if not requested_from then |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
347 return post_errors.new("from"); |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
348 end |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
349 if jid.compare(requested_from, from) then |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
350 from = requested_from; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
351 else |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
352 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
|
353 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
354 end |
4242
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4066
diff
changeset
|
355 |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
356 payload.attr = { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
357 from = from, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
358 to = to, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
359 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
|
360 type = payload.attr.type, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
361 ["xml:lang"] = payload.attr["xml:lang"], |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
362 }; |
4242
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4066
diff
changeset
|
363 |
5585
5b316088bef5
mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents:
5557
diff
changeset
|
364 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
|
365 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
|
366 |
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
367 if echo then |
4918
9d0ec61c70a1
mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents:
4888
diff
changeset
|
368 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
|
369 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
|
370 response.headers.content_type = send_type; |
4918
9d0ec61c70a1
mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents:
4888
diff
changeset
|
371 return ret; |
4514
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
372 end |
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
373 |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
374 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
|
375 local responses = st.stanza("xmpp"); |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
376 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
|
377 responses:add_direct_child(stanza); |
3910
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3909
diff
changeset
|
378 end |
4735 | 379 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
|
380 |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
381 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
|
382 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
|
383 elseif #payload.tags ~= 1 then |
4244
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4242
diff
changeset
|
384 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
|
385 end |
4242
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4066
diff
changeset
|
386 |
4942
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
387 -- 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:
4923
diff
changeset
|
388 -- 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:
4923
diff
changeset
|
389 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:
4923
diff
changeset
|
390 local archive_handler; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
391 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:
4923
diff
changeset
|
392 if archive_query then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
393 archive_handler = function(result_event) |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
394 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:
4923
diff
changeset
|
395 origin.send(result_event.stanza); |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
396 return true; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
397 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
398 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
399 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:
4923
diff
changeset
|
400 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
401 |
5332
e0b5468aae49
mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents:
5087
diff
changeset
|
402 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
|
403 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
|
404 |
e0b5468aae49
mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents:
5087
diff
changeset
|
405 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
|
406 function (result) |
5585
5b316088bef5
mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents:
5557
diff
changeset
|
407 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
|
408 response.headers.content_type = send_type; |
4944
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4943
diff
changeset
|
409 if responses[1] then |
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4943
diff
changeset
|
410 local tail = responses[#responses]; |
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4943
diff
changeset
|
411 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:
4943
diff
changeset
|
412 origin.send(result.stanza); |
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4943
diff
changeset
|
413 end |
4943
83a54f4af94c
mod_rest: Ensure MAM result-iq is included in results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4942
diff
changeset
|
414 end |
4699
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4532
diff
changeset
|
415 if responses[2] then |
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4532
diff
changeset
|
416 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
|
417 end |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
418 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
|
419 end, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
420 function (error) |
3909
eb27e51cf2c9
mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents:
3887
diff
changeset
|
421 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
|
422 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
|
423 return select(2, errors.coerce(nil, error)); |
eb27e51cf2c9
mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents:
3887
diff
changeset
|
424 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
|
425 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
|
426 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
|
427 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
|
428 else |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
429 return error; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
430 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
431 end); |
4942
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
432 |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
433 if archive_handler then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
434 p:finally(function () |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
435 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:
4923
diff
changeset
|
436 end) |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
437 end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
438 |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4923
diff
changeset
|
439 return p; |
3805
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3804
diff
changeset
|
440 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
|
441 function origin.send(stanza) |
5585
5b316088bef5
mod_rest: Use logger of HTTP request in trunk
Kim Alvefur <zash@zash.se>
parents:
5557
diff
changeset
|
442 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
|
443 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
|
444 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
|
445 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
|
446 end |
4735 | 447 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
|
448 |
3814
0dede5b0ab27
mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents:
3813
diff
changeset
|
449 module:send(payload, origin); |
0dede5b0ab27
mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents:
3813
diff
changeset
|
450 return 202; |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
451 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
452 end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
453 |
4888
dc7c9ae15f43
mod_rest: Ensure mod_http is loaded before API demo
Kim Alvefur <zash@zash.se>
parents:
4841
diff
changeset
|
454 module:depends("http"); |
dc7c9ae15f43
mod_rest: Ensure mod_http is loaded before API demo
Kim Alvefur <zash@zash.se>
parents:
4841
diff
changeset
|
455 |
4488
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
456 local demo_handlers = {}; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
457 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
|
458 demo_handlers = module:require"apidemo"; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
459 end |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
460 |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
461 -- Handle stanzas submitted via HTTP |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
462 module:provides("http", { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
463 route = { |
4478
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
464 POST = handle_request; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
465 ["POST /*"] = handle_request; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4477
diff
changeset
|
466 ["GET /*"] = handle_request; |
4488
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
467 |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
468 -- 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
|
469 ["GET /"] = demo_handlers.redirect; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
470 ["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
|
471 ["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
|
472 ["GET /demo/*"] = demo_handlers.resources; |
3794
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
473 }; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
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 |
5087
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5086
diff
changeset
|
476 function new_webhook(rest_url, send_type) |
4921
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
477 local function get_url() return rest_url; end |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
478 if rest_url:find("%b{}") then |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
479 local httputil = require "util.http"; |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
480 local render_url = require"util.interpolation".new("%b{}", httputil.urlencode); |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
481 function get_url(stanza) |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
482 local at = stanza.attr; |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
483 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:
4919
diff
changeset
|
484 end |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
485 end |
3813 | 486 if send_type == "json" then |
487 send_type = "application/json"; | |
488 end | |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
489 |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
490 module:set_status("info", "Not yet connected"); |
4921
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
491 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
|
492 method = "OPTIONS", |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
493 }, function (body, code, response) |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
494 if code == 0 then |
4922
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
495 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:
4921
diff
changeset
|
496 elseif code == 200 then |
3862
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3861
diff
changeset
|
497 module:set_status("info", "Connected"); |
4922
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
498 if response.headers.accept then |
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
499 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:
4921
diff
changeset
|
500 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:
4921
diff
changeset
|
501 end |
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
502 else |
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
503 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:
4921
diff
changeset
|
504 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
|
505 end |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
506 end); |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3858
diff
changeset
|
507 |
4245
7bf3bf81c9ef
mod_rest: Use HTTP error mapping from net.http.errors
Kim Alvefur <zash@zash.se>
parents:
4244
diff
changeset
|
508 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
|
509 |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
510 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
|
511 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
|
512 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
|
513 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
|
514 local receipt; |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
515 |
4250
8b489203e4d3
mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
516 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
|
517 reply_needed = true; |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
518 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
|
519 end |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
520 |
3812
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
521 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
|
522 |
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
523 -- 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
|
524 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
|
525 |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
526 module:log("debug", "Sending[rest]: %s", stanza:top_tag()); |
4921
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4919
diff
changeset
|
527 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
|
528 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
|
529 headers = { |
3811
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3810
diff
changeset
|
530 ["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
|
531 ["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
|
532 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
|
533 }, |
4247
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4245
diff
changeset
|
534 }):next(function (response) |
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4245
diff
changeset
|
535 module:set_status("info", "Connected"); |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
536 local reply; |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
537 |
4247
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4245
diff
changeset
|
538 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
|
539 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
|
540 return; |
8b489203e4d3
mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
541 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
|
542 if not reply_needed then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
543 -- Delivered, no reply |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
544 return; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
545 end |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
546 else |
3867
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
547 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
|
548 if not parsed then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
549 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
|
550 elseif parsed.name ~= stanza.name then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
551 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
|
552 else |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
553 parsed.attr = { |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
554 from = stanza.attr.to, |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
555 to = stanza.attr.from, |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
556 id = parsed.attr.id or id.medium(); |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
557 type = parsed.attr.type, |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
558 ["xml:lang"] = parsed.attr["xml:lang"], |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
559 }; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
560 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
|
561 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
|
562 end |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
563 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
|
564 parsed.attr.type = "error"; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
565 end |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
566 if parsed.attr.type == "error" then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
567 parsed.attr.id = stanza.attr.id; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
568 elseif parsed.name == "iq" then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
569 parsed.attr.id = stanza.attr.id; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
570 parsed.attr.type = "result"; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
571 end |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3866
diff
changeset
|
572 reply = parsed; |
3821
11272a3233ce
mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents:
3816
diff
changeset
|
573 end |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
574 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
575 |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
576 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
|
577 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
|
578 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
|
579 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
|
580 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
|
581 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
|
582 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
583 -- 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
|
584 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
|
585 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
|
586 elseif code_hundreds == 400 then |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
587 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
|
588 elseif code_hundreds == 500 then |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
589 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
|
590 else |
3810
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3807
diff
changeset
|
591 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
|
592 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
593 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
594 |
3798
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
595 if receipt then |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
596 reply:add_direct_child(receipt); |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
597 end |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3797
diff
changeset
|
598 |
3803
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
599 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
|
600 |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
601 origin.send(reply); |
4247
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4245
diff
changeset
|
602 end, |
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4245
diff
changeset
|
603 function (err) |
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4245
diff
changeset
|
604 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
|
605 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
|
606 end):catch(function (err) |
64aa1d9d70ac
mod_rest: Catch and log errors in callback promise chain
Kim Alvefur <zash@zash.se>
parents:
4247
diff
changeset
|
607 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
|
608 end); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
609 |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
610 return true; |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
611 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
612 |
5087
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5086
diff
changeset
|
613 return handle_stanza; |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5086
diff
changeset
|
614 end |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5086
diff
changeset
|
615 |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5086
diff
changeset
|
616 -- 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
|
617 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
|
618 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
|
619 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
|
620 |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5086
diff
changeset
|
621 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
|
622 |
4923
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
623 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:
4922
diff
changeset
|
624 |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
625 local event_presets = { |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
626 -- 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:
4922
diff
changeset
|
627 ["local"] = { "host" }, |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
628 -- 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:
4922
diff
changeset
|
629 ["component"] = { "bare", "full", "host" }, |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
630 }; |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
631 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:
4922
diff
changeset
|
632 for kind in send_kinds do |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
633 for event in hook_events do |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
634 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:
4922
diff
changeset
|
635 end |
3795
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
636 end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3794
diff
changeset
|
637 end |
3842
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
638 |
3929
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
639 local supported_errors = { |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
640 "text/html", |
3931
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
641 "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
|
642 "application/json", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
643 }; |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3926
diff
changeset
|
644 |
3873
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
645 local http_server = require "net.http.server"; |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
646 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
|
647 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
|
648 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
|
649 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
|
650 if response then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
651 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
|
652 end |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
653 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
|
654 if event.error then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
655 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
|
656 if event.error.text then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
657 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
|
658 end |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
659 end |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
660 return tostring(stream_error); |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
661 elseif response_as == "application/json" then |
3873
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
662 if response then |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
663 response.headers.content_type = "application/json"; |
3842
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3832
diff
changeset
|
664 end |
3873
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
665 return json.encode({ |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
666 type = "error", |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
667 error = event.error, |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
668 code = event.code, |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
669 }); |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3872
diff
changeset
|
670 end |
3933
93147b89ea67
mod_rest: Avoid interfering with mod_http_oauth2 errors (fixes #1500)
Kim Alvefur <zash@zash.se>
parents:
3931
diff
changeset
|
671 end, 1); |