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