Comparison

mod_rest/mod_rest.lua @ 3794:4b258329e6e4

mod_rest: Initial commit of another RESTful API module
author Kim Alvefur <zash@zash.se>
date Mon, 30 Dec 2019 04:04:34 +0100
child 3795:f51308fcba83
comparison
equal deleted inserted replaced
3793:0d3926e49b55 3794: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 });