mod_rest/mod_rest.lua
changeset 3798 4b258329e6e4
child 3799 f51308fcba83
equal deleted inserted replaced
3797:0d3926e49b55 3798:4b258329e6e4
       
     1 -- RESTful API
       
     2 --
       
     3 -- Copyright (c) 2019 Kim Alvefur
       
     4 --
       
     5 -- This file is MIT/X11 licensed.
       
     6 
       
     7 local errors = require "util.error";
       
     8 local id = require "util.id";
       
     9 local jid = require "util.jid";
       
    10 local xml = require "util.xml";
       
    11 
       
    12 local allow_any_source = module:get_host_type() == "component";
       
    13 local validate_from_addresses = module:get_option_boolean("validate_from_addresses", true);
       
    14 
       
    15 local function handle_post(event)
       
    16 	local request, response = event.request, event.response;
       
    17 	if request.headers.content_type ~= "application/xmpp+xml" then
       
    18 		return errors.new({ code = 415, text = "'application/xmpp+xml' expected"  });
       
    19 	end
       
    20 	local payload, err = xml.parse(request.body);
       
    21 	if not payload then
       
    22 		-- parse fail
       
    23 		return errors.new({ code = 400, text = err });
       
    24 	end
       
    25 	local to = jid.prep(payload.attr.to);
       
    26 	if not to then
       
    27 		return errors.new({ code = 400, text = "Invalid destination JID" });
       
    28 	end
       
    29 	local from = module.host;
       
    30 	if allow_any_source and payload.attr.from then
       
    31 		from = jid.prep(payload.attr.from);
       
    32 		if not from then
       
    33 			return errors.new({ code = 400, text = "Invalid source JID" });
       
    34 		end
       
    35 		if validate_from_addresses and not jid.compare(from, module.host) then
       
    36 			return errors.new({ code = 403, text = "Source JID must belong to current host" });
       
    37 		end
       
    38 	end
       
    39 	payload.attr = {
       
    40 		from = from,
       
    41 		to = to,
       
    42 		id = payload.attr.id or id.medium(),
       
    43 		type = payload.attr.type,
       
    44 		["xml:lang"] = payload.attr["xml:lang"],
       
    45 	};
       
    46 	if payload.name == "iq" then
       
    47 		if payload.attr.type ~= "get" and payload.attr.type ~= "set" then
       
    48 			return errors.new({ code = 400, text = "'iq' stanza must be of type 'get' or 'set'" });
       
    49 		end
       
    50 		return module:send_iq(payload):next(
       
    51 			function (result)
       
    52 				response.headers.content_type = "application/xmpp+xml";
       
    53 				return tostring(result.stanza);
       
    54 			end,
       
    55 			function (error)
       
    56 				if error.context.stanza then
       
    57 					response.headers.content_type = "application/xmpp+xml";
       
    58 					return tostring(error.context.stanza);
       
    59 				else
       
    60 					return error;
       
    61 				end
       
    62 			end);
       
    63 	elseif payload.name == "message" or payload.name == "presence" then
       
    64 		if module:send(payload) then
       
    65 			return 202;
       
    66 		else
       
    67 			return 500;
       
    68 		end
       
    69 	else
       
    70 		return errors.new({ code = 400, text = "Invalid stanza, must be 'message', 'presence' or 'iq'." });
       
    71 	end
       
    72 end
       
    73 
       
    74 -- Handle stanzas submitted via HTTP
       
    75 module:depends("http");
       
    76 module:provides("http", {
       
    77 		route = {
       
    78 			POST = handle_post;
       
    79 		};
       
    80 	});