Comparison

mod_rest/mod_rest.lua @ 4920:bdac7c717c91

mod_rest: Support parameters in callback URL E.g. rest_callback_url = "http://myapi.example:5000/api/{kind}/{type}" which results in e.g. requests to /api/message/chat Allows using path routing in web frameworks for dispatch instead of having to pick apart the payload to further dispatch it.
author Kim Alvefur <zash@zash.se>
date Sat, 09 Apr 2022 00:41:18 +0200
parent 4918:347e34c3c7e2
child 4921:816b23e09c20
comparison
equal deleted inserted replaced
4919:b9f8dd9a7fdb 4920:bdac7c717c91
1 -- RESTful API 1 -- RESTful API
2 -- 2 --
3 -- Copyright (c) 2019-2020 Kim Alvefur 3 -- Copyright (c) 2019-2022 Kim Alvefur
4 -- 4 --
5 -- This file is MIT/X11 licensed. 5 -- This file is MIT/X11 licensed.
6 6
7 local encodings = require "util.encodings"; 7 local encodings = require "util.encodings";
8 local base64 = encodings.base64; 8 local base64 = encodings.base64;
414 }); 414 });
415 415
416 -- Forward stanzas from XMPP to HTTP and return any reply 416 -- Forward stanzas from XMPP to HTTP and return any reply
417 local rest_url = module:get_option_string("rest_callback_url", nil); 417 local rest_url = module:get_option_string("rest_callback_url", nil);
418 if rest_url then 418 if rest_url then
419 local function get_url() return rest_url; end
420 if rest_url:find("%b{}") then
421 local httputil = require "util.http";
422 local render_url = require"util.interpolation".new("%b{}", httputil.urlencode);
423 function get_url(stanza)
424 local at = stanza.attr;
425 return render_url(rest_url, { kind = stanza.name, type = at.type, to = at.to, from = at.from });
426 end
427 end
419 local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml"); 428 local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml");
420 if send_type == "json" then 429 if send_type == "json" then
421 send_type = "application/json"; 430 send_type = "application/json";
422 end 431 end
423 432
424 module:set_status("info", "Not yet connected"); 433 module:set_status("info", "Not yet connected");
425 http.request(rest_url, { 434 http.request(get_url(st.stanza("meta", { type = "info", to = module.host, from = module.host })), {
426 method = "OPTIONS", 435 method = "OPTIONS",
427 }, function (body, code, response) 436 }, function (body, code, response)
428 if code == 0 then 437 if code == 0 then
429 return module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, body); 438 return module:log_status("error", "Could not connect to callback URL %q: %s", rest_url, body);
430 else 439 else
453 462
454 -- Keep only the top level element and let the rest be GC'd 463 -- Keep only the top level element and let the rest be GC'd
455 stanza = st.clone(stanza, true); 464 stanza = st.clone(stanza, true);
456 465
457 module:log("debug", "Sending[rest]: %s", stanza:top_tag()); 466 module:log("debug", "Sending[rest]: %s", stanza:top_tag());
458 http.request(rest_url, { 467 http.request(get_url(stanza), {
459 body = request_body, 468 body = request_body,
460 headers = { 469 headers = {
461 ["Content-Type"] = send_type, 470 ["Content-Type"] = send_type,
462 ["Content-Language"] = stanza.attr["xml:lang"], 471 ["Content-Language"] = stanza.attr["xml:lang"],
463 Accept = table.concat(supported_inputs, ", "); 472 Accept = table.concat(supported_inputs, ", ");