Software / code / prosody-modules
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 }); |