author | Kim Alvefur <zash@zash.se> |
Thu, 22 Jun 2023 22:00:51 +0200 | |
changeset 5567 | a1f8cc591b66 |
parent 5561 | d7667d9ad96a |
child 5589 | 5b316088bef5 |
permissions | -rw-r--r-- |
3798
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 |
-- |
4924
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
3 |
-- Copyright (c) 2019-2022 Kim Alvefur |
3798
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 |
|
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
7 |
local encodings = require "util.encodings"; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
8 |
local base64 = encodings.base64; |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
9 |
local errors = require "util.error"; |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
10 |
local http = require "net.http"; |
3798
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"; |
3817 | 13 |
local json = require "util.json"; |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
14 |
local st = require "util.stanza"; |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
15 |
local um = require "core.usermanager"; |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
16 |
local xml = require "util.xml"; |
4041 | 17 |
local have_cbor, cbor = pcall(require, "cbor"); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
18 |
|
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
19 |
local jsonmap = module:require"jsonmap"; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
20 |
|
3919
80dffbbd056b
mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents:
3915
diff
changeset
|
21 |
local tokens = module:depends("tokenauth"); |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
22 |
|
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
23 |
local auth_mechanisms = module:get_option_set("rest_auth_mechanisms", { "Basic", "Bearer" }); |
3806
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3805
diff
changeset
|
24 |
|
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
25 |
local www_authenticate_header; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
26 |
do |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
27 |
local header, realm = {}, module.host.."/"..module.name; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
28 |
for mech in auth_mechanisms do |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
29 |
header[#header+1] = ("%s realm=%q"):format(mech, realm); |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
30 |
end |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
31 |
www_authenticate_header = table.concat(header, ", "); |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
32 |
end |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
33 |
|
3806
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3805
diff
changeset
|
34 |
local function check_credentials(request) |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
35 |
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:
3913
diff
changeset
|
36 |
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:
3913
diff
changeset
|
37 |
return false; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
38 |
end |
3880
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
39 |
|
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
40 |
if auth_type == "Basic" then |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
41 |
local creds = base64.decode(auth_data); |
3880
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
42 |
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:
3878
diff
changeset
|
43 |
local username, password = string.match(creds, "^([^:]+):(.*)$"); |
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
44 |
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:
3878
diff
changeset
|
45 |
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:
3878
diff
changeset
|
46 |
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:
3878
diff
changeset
|
47 |
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:
3878
diff
changeset
|
48 |
return false; |
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
49 |
end |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
50 |
return { username = username, host = module.host }; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
51 |
elseif auth_type == "Bearer" then |
5005
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4992
diff
changeset
|
52 |
if tokens.get_token_session then |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4992
diff
changeset
|
53 |
return tokens.get_token_session(auth_data); |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4992
diff
changeset
|
54 |
else -- COMPAT w/0.12 |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4992
diff
changeset
|
55 |
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:
4992
diff
changeset
|
56 |
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:
4992
diff
changeset
|
57 |
return false; |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4992
diff
changeset
|
58 |
end |
cb19cb1c03d6
mod_rest: Update for mod_tokenauth API changes (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4992
diff
changeset
|
59 |
return token_info.session; |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
60 |
end |
3880
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
61 |
end |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
62 |
return nil; |
3880
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
63 |
end |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
64 |
|
4738
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
65 |
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:
4731
diff
changeset
|
66 |
www_authenticate_header = nil; |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
67 |
function check_credentials(request) -- luacheck: ignore 212/request |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
68 |
return { |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
69 |
username = id.medium():lower(); |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
70 |
host = module.host; |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
71 |
} |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
72 |
end |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
73 |
end |
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
74 |
|
4945
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
75 |
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:
4926
diff
changeset
|
76 |
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:
4926
diff
changeset
|
77 |
if node then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
78 |
if resource then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
79 |
return '/full'; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
80 |
else |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
81 |
return '/bare'; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
82 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
83 |
else |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
84 |
return '/host'; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
85 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
86 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
87 |
|
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
88 |
|
4739 | 89 |
-- TODO This ought to be handled some way other than duplicating this |
90 |
-- core.stanza_router code here. |
|
91 |
local function compat_preevents(origin, stanza) --> boolean : handled |
|
92 |
local to = stanza.attr.to; |
|
93 |
local node, host, resource = jid.split(to); |
|
94 |
||
95 |
local to_type, to_self; |
|
96 |
if node then |
|
97 |
if resource then |
|
98 |
to_type = '/full'; |
|
99 |
else |
|
100 |
to_type = '/bare'; |
|
101 |
if node == origin.username and host == origin.host then |
|
102 |
stanza.attr.to = nil; |
|
103 |
to_self = true; |
|
104 |
end |
|
105 |
end |
|
106 |
else |
|
107 |
if host then |
|
108 |
to_type = '/host'; |
|
109 |
else |
|
110 |
to_type = '/bare'; |
|
111 |
to_self = true; |
|
112 |
end |
|
113 |
end |
|
114 |
||
115 |
local event_data = { origin = origin; stanza = stanza; to_self = to_self }; |
|
116 |
||
117 |
local result = module:fire_event("pre-stanza", event_data); |
|
118 |
if result ~= nil then return true end |
|
119 |
if module:fire_event('pre-' .. stanza.name .. to_type, event_data) then return true; end -- do preprocessing |
|
120 |
return false |
|
121 |
end |
|
122 |
||
4481
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
123 |
-- (table, string) -> table |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
124 |
local function amend_from_path(data, path) |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
125 |
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:
4254
diff
changeset
|
126 |
if not st_kind then return; end |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
127 |
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:
4481
diff
changeset
|
128 |
-- GET /iq/disco/jid |
4507
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
129 |
data = { |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
130 |
kind = "iq"; |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
131 |
[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:
4506
diff
changeset
|
132 |
}; |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
133 |
else |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
134 |
data.kind = st_kind; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
135 |
data.type = st_type; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
136 |
end |
4481
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
137 |
if st_to and st_to ~= "" then |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
138 |
data.to = st_to; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
139 |
end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
140 |
return data; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
141 |
end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
142 |
|
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
143 |
local function parse(mimetype, data, path) --> Stanza, error enum |
3829
802087d3155a
mod_rest: Fix traceback on missing content-type header
Kim Alvefur <zash@zash.se>
parents:
3828
diff
changeset
|
144 |
mimetype = mimetype and mimetype:match("^[^; ]*"); |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
145 |
if mimetype == "application/xmpp+xml" then |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
146 |
return xml.parse(data); |
3817 | 147 |
elseif mimetype == "application/json" then |
148 |
local parsed, err = json.decode(data); |
|
149 |
if not parsed then |
|
150 |
return parsed, err; |
|
151 |
end |
|
4507
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
152 |
if path then |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
153 |
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:
4506
diff
changeset
|
154 |
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:
4506
diff
changeset
|
155 |
end |
3817 | 156 |
return jsonmap.json2st(parsed); |
4041 | 157 |
elseif mimetype == "application/cbor" and have_cbor then |
158 |
local parsed, err = cbor.decode(data); |
|
159 |
if not parsed then |
|
160 |
return parsed, err; |
|
161 |
end |
|
162 |
return jsonmap.json2st(parsed); |
|
3915
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
163 |
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:
3914
diff
changeset
|
164 |
local parsed = http.formdecode(data); |
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
165 |
if type(parsed) == "string" then |
4507
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
166 |
-- 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:
4506
diff
changeset
|
167 |
if path then |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
168 |
return nil, "invalid-query"; |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
169 |
end |
3915
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
170 |
return parse("text/plain", parsed); |
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
171 |
end |
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
172 |
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:
3914
diff
changeset
|
173 |
parsed[i] = nil; |
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
174 |
end |
4507
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
175 |
if path then |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
176 |
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:
4506
diff
changeset
|
177 |
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:
4506
diff
changeset
|
178 |
end |
3915
064c32a5be7c
mod_rest: Support urlencoded form data (does a subset of JSON mapping)
Kim Alvefur <zash@zash.se>
parents:
3914
diff
changeset
|
179 |
return jsonmap.json2st(parsed); |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
180 |
elseif mimetype == "text/plain" then |
4481
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
181 |
if not path then |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
182 |
return st.message({ type = "chat" }, data); |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
183 |
end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
184 |
local parsed = {}; |
4507
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
185 |
if path then |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
186 |
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:
4506
diff
changeset
|
187 |
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:
4506
diff
changeset
|
188 |
end |
4481
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
189 |
if parsed.kind == "message" then |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
190 |
parsed.body = data; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
191 |
elseif parsed.kind == "presence" then |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
192 |
parsed.show = data; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
193 |
else |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
194 |
return nil, "invalid-path"; |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
195 |
end |
8df6cc648963
mod_rest: Add more REST-looking way to send stanzas
Kim Alvefur <zash@zash.se>
parents:
4254
diff
changeset
|
196 |
return jsonmap.json2st(parsed); |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
197 |
elseif not mimetype and path then |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
198 |
local parsed = amend_from_path({}, path); |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
199 |
if not parsed then return nil, "invalid-path"; end |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
200 |
return jsonmap.json2st(parsed); |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
201 |
end |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
202 |
return nil, "unknown-payload-type"; |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
203 |
end |
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
204 |
|
3933
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
205 |
local function decide_type(accept, supported_types) |
3817 | 206 |
-- assumes the accept header is sorted |
207 |
local ret = supported_types[1]; |
|
208 |
for i = 2, #supported_types do |
|
209 |
if (accept:find(supported_types[i], 1, true) or 1000) < (accept:find(ret, 1, true) or 1000) then |
|
210 |
ret = supported_types[i]; |
|
211 |
end |
|
212 |
end |
|
213 |
return ret; |
|
3815
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3814
diff
changeset
|
214 |
end |
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3814
diff
changeset
|
215 |
|
3933
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
216 |
local supported_inputs = { |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
217 |
"application/xmpp+xml", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
218 |
"application/json", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
219 |
"application/x-www-form-urlencoded", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
220 |
"text/plain", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
221 |
}; |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
222 |
|
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
223 |
local supported_outputs = { |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
224 |
"application/xmpp+xml", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
225 |
"application/json", |
4070
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
226 |
"application/x-www-form-urlencoded", |
3933
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
227 |
}; |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
228 |
|
4041 | 229 |
if have_cbor then |
230 |
table.insert(supported_inputs, "application/cbor"); |
|
231 |
table.insert(supported_outputs, "application/cbor"); |
|
232 |
end |
|
233 |
||
4070
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
234 |
-- 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:
4041
diff
changeset
|
235 |
-- (jsonmap also discards anything unknown or unsupported) |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
236 |
local function flatten(t) |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
237 |
local form = {}; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
238 |
for k, v in pairs(t) do |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
239 |
if type(v) == "string" then |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
240 |
form[k] = v; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
241 |
elseif type(v) == "number" then |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
242 |
form[k] = tostring(v); |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
243 |
elseif v == true then |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
244 |
form[k] = ""; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
245 |
end |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
246 |
end |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
247 |
return form; |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
248 |
end |
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
249 |
|
3816
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
250 |
local function encode(type, s) |
4922
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
251 |
if type == "text/plain" then |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
252 |
return s:get_child_text("body") or ""; |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
253 |
elseif type == "application/xmpp+xml" then |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
254 |
return tostring(s); |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
255 |
end |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
256 |
local mapped, err = jsonmap.st2json(s); |
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
257 |
if not mapped then return mapped, err; end |
3817 | 258 |
if type == "application/json" then |
4922
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
259 |
return json.encode(mapped); |
4070
07ae583bc565
mod_rest: Add support for form-encoded output
Kim Alvefur <zash@zash.se>
parents:
4041
diff
changeset
|
260 |
elseif type == "application/x-www-form-urlencoded" then |
4922
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
261 |
return http.formencode(flatten(mapped)); |
4041 | 262 |
elseif type == "application/cbor" then |
4922
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
263 |
return cbor.encode(mapped); |
3817 | 264 |
end |
4922
347e34c3c7e2
mod_rest: Improve error handling during format mapping
Kim Alvefur <zash@zash.se>
parents:
4921
diff
changeset
|
265 |
error "unsupported encoding"; |
3816
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
266 |
end |
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
267 |
|
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
268 |
local post_errors = errors.init("mod_rest", { |
4992
732229fe68ab
mod_rest: Fill in 'type' field in error registry
Kim Alvefur <zash@zash.se>
parents:
4959
diff
changeset
|
269 |
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:
4959
diff
changeset
|
270 |
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:
4959
diff
changeset
|
271 |
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:
4959
diff
changeset
|
272 |
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:
4959
diff
changeset
|
273 |
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:
4959
diff
changeset
|
274 |
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:
4959
diff
changeset
|
275 |
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:
4959
diff
changeset
|
276 |
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:
4959
diff
changeset
|
277 |
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:
4959
diff
changeset
|
278 |
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:
4959
diff
changeset
|
279 |
mediatype = { code = 415; type = "cancel"; condition = "bad-format"; text = "Unsupported media type" }; |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
280 |
}); |
3934
d5dafd617cd6
mod_rest: Break out POST errors into a registry
Kim Alvefur <zash@zash.se>
parents:
3933
diff
changeset
|
281 |
|
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
282 |
-- GET → iq-get |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
283 |
local function parse_request(request, path) |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
284 |
if path and request.method == "GET" then |
4510
508cb880b163
mod_rest: Fix typos [codespell]
Kim Alvefur <zash@zash.se>
parents:
4507
diff
changeset
|
285 |
-- e.g. /version/{to} |
4507
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
286 |
if request.url.query then |
80912726405d
mod_rest: Allow passing e.g. disco 'node' as a ?query variable
Kim Alvefur <zash@zash.se>
parents:
4506
diff
changeset
|
287 |
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:
4506
diff
changeset
|
288 |
end |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
289 |
return parse(nil, nil, "iq/"..path); |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
290 |
else |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
291 |
return parse(request.headers.content_type, request.body, path); |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
292 |
end |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
293 |
end |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
294 |
|
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
295 |
local function handle_request(event, path) |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
296 |
local request, response = event.request, event.response; |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
297 |
local from; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
298 |
local origin; |
4518
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
299 |
local echo = path == "echo"; |
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
300 |
if echo then path = nil; end |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
301 |
|
4738
e58ec4b3cf90
mod_rest: Add an anonymous mode
Kim Alvefur <zash@zash.se>
parents:
4731
diff
changeset
|
302 |
if not request.headers.authorization and www_authenticate_header then |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
303 |
response.headers.www_authenticate = www_authenticate_header; |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
304 |
return post_errors.new("noauthz"); |
3880
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
305 |
else |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
306 |
origin = check_credentials(request); |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
307 |
if not origin then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
308 |
return post_errors.new("unauthz"); |
3880
75b330d4fa6f
mod_rest: Add support for HTTP Basic username and password authentication
Kim Alvefur <zash@zash.se>
parents:
3878
diff
changeset
|
309 |
end |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
310 |
from = jid.join(origin.username, origin.host, origin.resource); |
5561
d7667d9ad96a
mod_rest: Include full_jid property on origin
Kim Alvefur <zash@zash.se>
parents:
5338
diff
changeset
|
311 |
origin.full_jid = from; |
4731
e6f46d1b3337
mod_rest: Set type on temp session to satisfy certain auth checks
Kim Alvefur <zash@zash.se>
parents:
4703
diff
changeset
|
312 |
origin.type = "c2s"; |
4959
537054999093
mod_rest: Provide a log function on temporary session
Kim Alvefur <zash@zash.se>
parents:
4947
diff
changeset
|
313 |
origin.log = module._log; |
3806
f88e07630e4e
mod_rest: Add support for simple Bearer token auth
Kim Alvefur <zash@zash.se>
parents:
3805
diff
changeset
|
314 |
end |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
315 |
local payload, err = parse_request(request, path); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
316 |
if not payload then |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
317 |
-- parse fail |
4040
04c11b652aeb
mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents:
3975
diff
changeset
|
318 |
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:
3975
diff
changeset
|
319 |
if err == "unknown-payload-type" then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
320 |
return post_errors.new("mediatype", ctx); |
4040
04c11b652aeb
mod_rest: Respond to unknown payload types with HTTP status 415
Kim Alvefur <zash@zash.se>
parents:
3975
diff
changeset
|
321 |
end |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
322 |
return post_errors.new("parse", ctx); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
323 |
end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
324 |
|
4845
f69c5a443156
mod_rest: Fix nested message stanzas in XEP-0297 containers
Kim Alvefur <zash@zash.se>
parents:
4749
diff
changeset
|
325 |
if (payload.attr.xmlns or "jabber:client") ~= "jabber:client" then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
326 |
return post_errors.new("xmlns"); |
3809
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3808
diff
changeset
|
327 |
elseif payload.name ~= "message" and payload.name ~= "presence" and payload.name ~= "iq" then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
328 |
return post_errors.new("name"); |
3805
d59fb4dcf100
mod_rest: Verify that @xmlns is left empty
Kim Alvefur <zash@zash.se>
parents:
3803
diff
changeset
|
329 |
end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
330 |
|
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
331 |
local to = jid.prep(payload.attr.to); |
4506
48afaec5d1de
mod_rest: Allow empty @to to mean to=account is in normal XMPP
Kim Alvefur <zash@zash.se>
parents:
4492
diff
changeset
|
332 |
if payload.attr.to and not to then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
333 |
return post_errors.new("to"); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
334 |
end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
335 |
|
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
336 |
if payload.attr.from then |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
337 |
local requested_from = jid.prep(payload.attr.from); |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
338 |
if not requested_from then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
339 |
return post_errors.new("from"); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
340 |
end |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
341 |
if jid.compare(requested_from, from) then |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
342 |
from = requested_from; |
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
343 |
else |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
344 |
return post_errors.new("from_auth"); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
345 |
end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
346 |
end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
347 |
|
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
348 |
payload.attr = { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
349 |
from = from, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
350 |
to = to, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
351 |
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
|
352 |
type = payload.attr.type, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
353 |
["xml:lang"] = payload.attr["xml:lang"], |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
354 |
}; |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
355 |
|
3807
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3806
diff
changeset
|
356 |
module:log("debug", "Received[rest]: %s", payload:top_tag()); |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
357 |
local send_type = decide_type((request.headers.accept or "") ..",".. (request.headers.content_type or ""), supported_outputs) |
4518
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
358 |
|
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
359 |
if echo then |
4921
9d0ec61c70a1
mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents:
4892
diff
changeset
|
360 |
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:
4892
diff
changeset
|
361 |
if not ret then return err; end |
4518
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
362 |
response.headers.content_type = send_type; |
4921
9d0ec61c70a1
mod_rest: Catch and coerce errors in echo endpoint
Kim Alvefur <zash@zash.se>
parents:
4892
diff
changeset
|
363 |
return ret; |
4518
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
364 |
end |
81d0748bff5b
mod_rest: Add an 'echo' endpoint for debugging
Kim Alvefur <zash@zash.se>
parents:
4510
diff
changeset
|
365 |
|
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
366 |
if payload.name == "iq" then |
4703
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4536
diff
changeset
|
367 |
local responses = st.stanza("xmpp"); |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
368 |
function origin.send(stanza) |
4703
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4536
diff
changeset
|
369 |
responses:add_direct_child(stanza); |
3914
49efd1323a1b
mod_rest: Add support for token authentication
Matthew Wild <mwild1@gmail.com>
parents:
3913
diff
changeset
|
370 |
end |
4739 | 371 |
if compat_preevents(origin, payload) then return 202; end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
372 |
|
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
373 |
if payload.attr.type ~= "get" and payload.attr.type ~= "set" then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
374 |
return post_errors.new("iq_type"); |
3836
0d4146cf9fbc
mod_rest: Enforce single child policy for outgoing it stanzas
Kim Alvefur <zash@zash.se>
parents:
3829
diff
changeset
|
375 |
elseif #payload.tags ~= 1 then |
4248
07c11080027e
mod_rest: Use util.error registry datatype
Kim Alvefur <zash@zash.se>
parents:
4246
diff
changeset
|
376 |
return post_errors.new("iq_tags"); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
377 |
end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
378 |
|
4945
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
379 |
-- 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:
4926
diff
changeset
|
380 |
-- 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:
4926
diff
changeset
|
381 |
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:
4926
diff
changeset
|
382 |
local archive_handler; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
383 |
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:
4926
diff
changeset
|
384 |
if archive_query then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
385 |
archive_handler = function(result_event) |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
386 |
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:
4926
diff
changeset
|
387 |
origin.send(result_event.stanza); |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
388 |
return true; |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
389 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
390 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
391 |
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:
4926
diff
changeset
|
392 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
393 |
|
5336
e0b5468aae49
mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents:
5091
diff
changeset
|
394 |
local iq_timeout = tonumber(request.headers.prosody_rest_timeout) or module:get_option_number("rest_iq_timeout", 60*2); |
5338
3c51eab0afe8
mod_rest: Get correct type from config
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
395 |
iq_timeout = math.min(iq_timeout, module:get_option_number("rest_iq_max_timeout", 300)); |
5336
e0b5468aae49
mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents:
5091
diff
changeset
|
396 |
|
e0b5468aae49
mod_rest: Allow passing configuring a timeout for <iq> responses
Kim Alvefur <zash@zash.se>
parents:
5091
diff
changeset
|
397 |
local p = module:send_iq(payload, origin, iq_timeout):next( |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
398 |
function (result) |
3807
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3806
diff
changeset
|
399 |
module:log("debug", "Sending[rest]: %s", result.stanza:top_tag()); |
3815
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3814
diff
changeset
|
400 |
response.headers.content_type = send_type; |
4947
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4946
diff
changeset
|
401 |
if responses[1] then |
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4946
diff
changeset
|
402 |
local tail = responses[#responses]; |
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4946
diff
changeset
|
403 |
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:
4946
diff
changeset
|
404 |
origin.send(result.stanza); |
e67cc71727ca
mod_rest: Fix attempt to index nil in handling of single iq response
Kim Alvefur <zash@zash.se>
parents:
4946
diff
changeset
|
405 |
end |
4946
83a54f4af94c
mod_rest: Ensure MAM result-iq is included in results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4945
diff
changeset
|
406 |
end |
4703
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4536
diff
changeset
|
407 |
if responses[2] then |
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4536
diff
changeset
|
408 |
return encode(send_type, responses); |
a8af632daf48
mod_rest: Support returning multiple replies in an <xmpp> container
Kim Alvefur <zash@zash.se>
parents:
4536
diff
changeset
|
409 |
end |
3816
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
410 |
return encode(send_type, result.stanza); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
411 |
end, |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
412 |
function (error) |
3913
eb27e51cf2c9
mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents:
3891
diff
changeset
|
413 |
if not errors.is_err(error) then |
eb27e51cf2c9
mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents:
3891
diff
changeset
|
414 |
module:log("error", "Uncaught native error: %s", error); |
eb27e51cf2c9
mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents:
3891
diff
changeset
|
415 |
return select(2, errors.coerce(nil, error)); |
eb27e51cf2c9
mod_rest: Handle uncaught native errors correctly
Matthew Wild <mwild1@gmail.com>
parents:
3891
diff
changeset
|
416 |
elseif error.context and error.context.stanza then |
3815
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3814
diff
changeset
|
417 |
response.headers.content_type = send_type; |
3807
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3806
diff
changeset
|
418 |
module:log("debug", "Sending[rest]: %s", error.context.stanza:top_tag()); |
3816
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
419 |
return encode(send_type, error.context.stanza); |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
420 |
else |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
421 |
return error; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
422 |
end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
423 |
end); |
4945
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
424 |
|
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
425 |
if archive_handler then |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
426 |
p:finally(function () |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
427 |
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:
4926
diff
changeset
|
428 |
end) |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
429 |
end |
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
430 |
|
e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Kim Alvefur <zash@zash.se>
parents:
4926
diff
changeset
|
431 |
return p; |
3809
683b06c0348f
mod_rest: Validate stanza kind earlier
Kim Alvefur <zash@zash.se>
parents:
3808
diff
changeset
|
432 |
else |
3800
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3799
diff
changeset
|
433 |
function origin.send(stanza) |
3807
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3806
diff
changeset
|
434 |
module:log("debug", "Sending[rest]: %s", stanza:top_tag()); |
3815
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3814
diff
changeset
|
435 |
response.headers.content_type = send_type; |
3816
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
436 |
response:send(encode(send_type, stanza)); |
3800
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3799
diff
changeset
|
437 |
return true; |
d1ad10b76b00
mod_rest: Catch one (1) reply to a POST-ed stanza from an internal source
Kim Alvefur <zash@zash.se>
parents:
3799
diff
changeset
|
438 |
end |
4739 | 439 |
if compat_preevents(origin, payload) then return 202; end |
4246
6a91d217acc9
mod_rest: Add whitespace to improve readability, code navigation
Kim Alvefur <zash@zash.se>
parents:
4070
diff
changeset
|
440 |
|
3818
0dede5b0ab27
mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents:
3817
diff
changeset
|
441 |
module:send(payload, origin); |
0dede5b0ab27
mod_rest: Fix return status when sending and forgetting
Kim Alvefur <zash@zash.se>
parents:
3817
diff
changeset
|
442 |
return 202; |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
443 |
end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
444 |
end |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
445 |
|
4892
dc7c9ae15f43
mod_rest: Ensure mod_http is loaded before API demo
Kim Alvefur <zash@zash.se>
parents:
4845
diff
changeset
|
446 |
module:depends("http"); |
dc7c9ae15f43
mod_rest: Ensure mod_http is loaded before API demo
Kim Alvefur <zash@zash.se>
parents:
4845
diff
changeset
|
447 |
|
4492
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
448 |
local demo_handlers = {}; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
449 |
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:
4485
diff
changeset
|
450 |
demo_handlers = module:require"apidemo"; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
451 |
end |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
452 |
|
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
453 |
-- Handle stanzas submitted via HTTP |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
454 |
module:provides("http", { |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
455 |
route = { |
4482
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
456 |
POST = handle_request; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
457 |
["POST /*"] = handle_request; |
7ab0c423688a
mod_rest: Support GET for certain IQ queries
Kim Alvefur <zash@zash.se>
parents:
4481
diff
changeset
|
458 |
["GET /*"] = handle_request; |
4492
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
459 |
|
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
460 |
-- Only if api_demo_resources are set |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
461 |
["GET /"] = demo_handlers.redirect; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
462 |
["GET /demo/"] = demo_handlers.main_page; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
463 |
["GET /demo/openapi.yaml"] = demo_handlers.schema; |
eea62d30ae08
mod_rest: Add option for serving interactive openapi documentation
Kim Alvefur <zash@zash.se>
parents:
4485
diff
changeset
|
464 |
["GET /demo/*"] = demo_handlers.resources; |
3798
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
465 |
}; |
4b258329e6e4
mod_rest: Initial commit of another RESTful API module
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
466 |
}); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
467 |
|
5091
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
468 |
function new_webhook(rest_url, send_type) |
4924
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
469 |
local function get_url() return rest_url; end |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
470 |
if rest_url:find("%b{}") then |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
471 |
local httputil = require "util.http"; |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
472 |
local render_url = require"util.interpolation".new("%b{}", httputil.urlencode); |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
473 |
function get_url(stanza) |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
474 |
local at = stanza.attr; |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
475 |
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:
4922
diff
changeset
|
476 |
end |
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
477 |
end |
3817 | 478 |
if send_type == "json" then |
479 |
send_type = "application/json"; |
|
480 |
end |
|
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
481 |
|
3866
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3865
diff
changeset
|
482 |
module:set_status("info", "Not yet connected"); |
4924
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
483 |
http.request(get_url(st.stanza("meta", { type = "info", to = module.host, from = module.host })), { |
3865
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3862
diff
changeset
|
484 |
method = "OPTIONS", |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3862
diff
changeset
|
485 |
}, function (body, code, response) |
3866
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3865
diff
changeset
|
486 |
if code == 0 then |
4925
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4924
diff
changeset
|
487 |
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:
4924
diff
changeset
|
488 |
elseif code == 200 then |
3866
3b6b8dcff78e
mod_rest: Log connectivity problems via module status API
Kim Alvefur <zash@zash.se>
parents:
3865
diff
changeset
|
489 |
module:set_status("info", "Connected"); |
4925
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4924
diff
changeset
|
490 |
if response.headers.accept then |
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4924
diff
changeset
|
491 |
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:
4924
diff
changeset
|
492 |
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:
4924
diff
changeset
|
493 |
end |
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4924
diff
changeset
|
494 |
else |
816b23e09c20
mod_rest: Improve logging of results from callback startup probe
Kim Alvefur <zash@zash.se>
parents:
4924
diff
changeset
|
495 |
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:
4924
diff
changeset
|
496 |
module:log("warn", "Endpoint said: %s", body); |
3865
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3862
diff
changeset
|
497 |
end |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3862
diff
changeset
|
498 |
end); |
ede3d1724dd1
mod_rest: Attempt to auto-discover data type wanted by callback
Kim Alvefur <zash@zash.se>
parents:
3862
diff
changeset
|
499 |
|
4249
7bf3bf81c9ef
mod_rest: Use HTTP error mapping from net.http.errors
Kim Alvefur <zash@zash.se>
parents:
4248
diff
changeset
|
500 |
local code2err = require "net.http.errors".registry; |
3801
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3800
diff
changeset
|
501 |
|
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
502 |
local function handle_stanza(event) |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
503 |
local stanza, origin = event.stanza, event.origin; |
5090
dec4b2e31d1c
mod_rest: Do not allow replies to <iq type=result> from webhooks
Kim Alvefur <zash@zash.se>
parents:
5005
diff
changeset
|
504 |
local reply_allowed = stanza.attr.type ~= "error" and stanza.attr.type ~= "result"; |
4254
8b489203e4d3
mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents:
4253
diff
changeset
|
505 |
local reply_needed = reply_allowed and stanza.name == "iq"; |
3802
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
506 |
local receipt; |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
507 |
|
4254
8b489203e4d3
mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents:
4253
diff
changeset
|
508 |
if reply_allowed and stanza.name == "message" and stanza.attr.id and stanza:get_child("urn:xmpp:receipts", "request") then |
3802
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
509 |
reply_needed = true; |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
510 |
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:
3801
diff
changeset
|
511 |
end |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
512 |
|
3816
f027b8b1e794
mod_rest: Factor out serialization of outgoing stanzas
Kim Alvefur <zash@zash.se>
parents:
3815
diff
changeset
|
513 |
local request_body = encode(send_type, stanza); |
3803
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
514 |
|
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
515 |
-- 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:
3802
diff
changeset
|
516 |
stanza = st.clone(stanza, true); |
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
517 |
|
3807
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3806
diff
changeset
|
518 |
module:log("debug", "Sending[rest]: %s", stanza:top_tag()); |
4924
bdac7c717c91
mod_rest: Support parameters in callback URL
Kim Alvefur <zash@zash.se>
parents:
4922
diff
changeset
|
519 |
http.request(get_url(stanza), { |
3803
a1f1f703d604
mod_rest: Allow collection of original stanza after sending HTTP request
Kim Alvefur <zash@zash.se>
parents:
3802
diff
changeset
|
520 |
body = request_body, |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
521 |
headers = { |
3815
eb25110696cd
mod_rest: Factor out response content type selection
Kim Alvefur <zash@zash.se>
parents:
3814
diff
changeset
|
522 |
["Content-Type"] = send_type, |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
523 |
["Content-Language"] = stanza.attr["xml:lang"], |
3933
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
524 |
Accept = table.concat(supported_inputs, ", "); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
525 |
}, |
4251
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
526 |
}):next(function (response) |
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
527 |
module:set_status("info", "Connected"); |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
528 |
local reply; |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
529 |
|
4251
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
530 |
local code, body = response.code, response.body; |
4254
8b489203e4d3
mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents:
4253
diff
changeset
|
531 |
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:
4253
diff
changeset
|
532 |
return; |
8b489203e4d3
mod_rest: Ensure no attempt is made to reply to an error stanza
Kim Alvefur <zash@zash.se>
parents:
4253
diff
changeset
|
533 |
elseif code == 202 or code == 204 then |
3871
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
534 |
if not reply_needed then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
535 |
-- Delivered, no reply |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
536 |
return; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
537 |
end |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
538 |
else |
3871
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
539 |
local parsed, err = parse(response.headers["content-type"], body); |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
540 |
if not parsed then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
541 |
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:
3870
diff
changeset
|
542 |
elseif parsed.name ~= stanza.name then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
543 |
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:
3870
diff
changeset
|
544 |
else |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
545 |
parsed.attr = { |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
546 |
from = stanza.attr.to, |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
547 |
to = stanza.attr.from, |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
548 |
id = parsed.attr.id or id.medium(); |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
549 |
type = parsed.attr.type, |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
550 |
["xml:lang"] = parsed.attr["xml:lang"], |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
551 |
}; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
552 |
if parsed.name == "message" and parsed.attr.type == "groupchat" then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
553 |
parsed.attr.to = jid.bare(stanza.attr.from); |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
554 |
end |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
555 |
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:
3870
diff
changeset
|
556 |
parsed.attr.type = "error"; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
557 |
end |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
558 |
if parsed.attr.type == "error" then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
559 |
parsed.attr.id = stanza.attr.id; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
560 |
elseif parsed.name == "iq" then |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
561 |
parsed.attr.id = stanza.attr.id; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
562 |
parsed.attr.type = "result"; |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
563 |
end |
839224be5299
mod_rest: Skip attempting parse empty response
Kim Alvefur <zash@zash.se>
parents:
3870
diff
changeset
|
564 |
reply = parsed; |
3825
11272a3233ce
mod_rest: Fix replying to groupchat messages
Kim Alvefur <zash@zash.se>
parents:
3820
diff
changeset
|
565 |
end |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
566 |
end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
567 |
|
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
568 |
if not reply then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
569 |
local code_hundreds = code - (code % 100); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
570 |
if code_hundreds == 200 then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
571 |
reply = st.reply(stanza); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
572 |
if stanza.name ~= "iq" then |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
573 |
reply.attr.id = id.medium(); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
574 |
end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
575 |
-- TODO presence/status=body ? |
3801
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3800
diff
changeset
|
576 |
elseif code2err[code] then |
ed5d7586a61e
mod_rest: Map various HTTP status codes to XMPP stanza errors
Kim Alvefur <zash@zash.se>
parents:
3800
diff
changeset
|
577 |
reply = st.error_reply(stanza, errors.new(code, nil, code2err)); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
578 |
elseif code_hundreds == 400 then |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
579 |
reply = st.error_reply(stanza, "modify", "bad-request", body); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
580 |
elseif code_hundreds == 500 then |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
581 |
reply = st.error_reply(stanza, "cancel", "internal-server-error", body); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
582 |
else |
3814
91ff86fc3b20
mod_rest: Factor out payload parsing
Kim Alvefur <zash@zash.se>
parents:
3811
diff
changeset
|
583 |
reply = st.error_reply(stanza, "cancel", "undefined-condition", body); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
584 |
end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
585 |
end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
586 |
|
3802
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
587 |
if receipt then |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
588 |
reply:add_direct_child(receipt); |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
589 |
end |
9b4fd2553365
mod_rest: Handle receipt requests on message stanzas
Kim Alvefur <zash@zash.se>
parents:
3801
diff
changeset
|
590 |
|
3807
dc2b5a412286
mod_rest: Log sent and received stanzas in style of mod_c2s etc
Kim Alvefur <zash@zash.se>
parents:
3806
diff
changeset
|
591 |
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:
3806
diff
changeset
|
592 |
|
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
593 |
origin.send(reply); |
4251
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
594 |
end, |
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
595 |
function (err) |
1f93fa24611d
mod_rest: Use promise based HTTP client API
Kim Alvefur <zash@zash.se>
parents:
4249
diff
changeset
|
596 |
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:
4249
diff
changeset
|
597 |
origin.send(st.error_reply(stanza, "wait", "recipient-unavailable", err.text)); |
4253
64aa1d9d70ac
mod_rest: Catch and log errors in callback promise chain
Kim Alvefur <zash@zash.se>
parents:
4251
diff
changeset
|
598 |
end):catch(function (err) |
64aa1d9d70ac
mod_rest: Catch and log errors in callback promise chain
Kim Alvefur <zash@zash.se>
parents:
4251
diff
changeset
|
599 |
module:log("error", "Error[rest]: %s", err); |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
600 |
end); |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
601 |
|
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
602 |
return true; |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
603 |
end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
604 |
|
5091
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
605 |
return handle_stanza; |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
606 |
end |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
607 |
|
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
608 |
-- 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:
5090
diff
changeset
|
609 |
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:
5090
diff
changeset
|
610 |
if rest_url then |
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
611 |
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:
5090
diff
changeset
|
612 |
|
438fbebf74ac
mod_rest: Wrap webhook setup in a function for future reuse
Kim Alvefur <zash@zash.se>
parents:
5090
diff
changeset
|
613 |
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:
5090
diff
changeset
|
614 |
|
4926
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
615 |
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:
4925
diff
changeset
|
616 |
|
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
617 |
local event_presets = { |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
618 |
-- 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:
4925
diff
changeset
|
619 |
["local"] = { "host" }, |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
620 |
-- 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:
4925
diff
changeset
|
621 |
["component"] = { "bare", "full", "host" }, |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
622 |
}; |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
623 |
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:
4925
diff
changeset
|
624 |
for kind in send_kinds do |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
625 |
for event in hook_events do |
c83b009b5bc5
mod_rest: Add configuration of which stanzas to route to callback
Kim Alvefur <zash@zash.se>
parents:
4925
diff
changeset
|
626 |
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:
4925
diff
changeset
|
627 |
end |
3799
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
628 |
end |
f51308fcba83
mod_rest: Allow specifying a webhook/callback to handle incoming stanzas
Kim Alvefur <zash@zash.se>
parents:
3798
diff
changeset
|
629 |
end |
3846
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3836
diff
changeset
|
630 |
|
3933
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
631 |
local supported_errors = { |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
632 |
"text/html", |
3935
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
633 |
"application/xmpp+xml", |
3933
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
634 |
"application/json", |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
635 |
}; |
bd687d586a8a
mod_rest: Separate lists of mediatypes for input, output and errors
Kim Alvefur <zash@zash.se>
parents:
3930
diff
changeset
|
636 |
|
3877
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
637 |
local http_server = require "net.http.server"; |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
638 |
module:hook_object_event(http_server, "http-error", function (event) |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
639 |
local request, response = event.request, event.response; |
3935
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
640 |
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:
3934
diff
changeset
|
641 |
if response_as == "application/xmpp+xml" then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
642 |
if response then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
643 |
response.headers.content_type = "application/xmpp+xml"; |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
644 |
end |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
645 |
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:
3934
diff
changeset
|
646 |
if event.error then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
647 |
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:
3934
diff
changeset
|
648 |
if event.error.text then |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
649 |
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:
3934
diff
changeset
|
650 |
end |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
651 |
end |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
652 |
return tostring(stream_error); |
2e8b284ac8b3
mod_rest: Add an XML error formatter (fixes #1499)
Kim Alvefur <zash@zash.se>
parents:
3934
diff
changeset
|
653 |
elseif response_as == "application/json" then |
3877
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
654 |
if response then |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
655 |
response.headers.content_type = "application/json"; |
3846
501c7edc8c37
mod_rest: Encode errors as JSON
Kim Alvefur <zash@zash.se>
parents:
3836
diff
changeset
|
656 |
end |
3877
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
657 |
return json.encode({ |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
658 |
type = "error", |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
659 |
error = event.error, |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
660 |
code = event.code, |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
661 |
}); |
fea0c1bed1a0
mod_rest: Back out 513a8a7fab41
Kim Alvefur <zash@zash.se>
parents:
3876
diff
changeset
|
662 |
end |
3937
93147b89ea67
mod_rest: Avoid interfering with mod_http_oauth2 errors (fixes #1500)
Kim Alvefur <zash@zash.se>
parents:
3935
diff
changeset
|
663 |
end, 1); |