changeset 4921: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
parents b9f8dd9a7fdb
children 816b23e09c20
files mod_rest/README.markdown mod_rest/mod_rest.lua
diffstat 2 files changed, 16 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/mod_rest/README.markdown	Sat Apr 09 00:37:55 2022 +0200
+++ b/mod_rest/README.markdown	Sat Apr 09 00:41:18 2022 +0200
@@ -130,6 +130,10 @@
 rest_callback_url = "http://my-api.example:9999/stanzas"
 ```
 
+The callback URL supports a few variables from the stanza being sent,
+namely `{kind}` (e.g. message, presence, iq or meta) and ones
+corresponding to stanza attributes: `{type}`, `{to}` and `{from}`.
+
 The preferred format can be indicated via the Accept header in response
 to an OPTIONS probe that mod_rest does on startup, or by configuring:
 
--- a/mod_rest/mod_rest.lua	Sat Apr 09 00:37:55 2022 +0200
+++ b/mod_rest/mod_rest.lua	Sat Apr 09 00:41:18 2022 +0200
@@ -1,6 +1,6 @@
 -- RESTful API
 --
--- Copyright (c) 2019-2020 Kim Alvefur
+-- Copyright (c) 2019-2022 Kim Alvefur
 --
 -- This file is MIT/X11 licensed.
 
@@ -416,13 +416,22 @@
 -- Forward stanzas from XMPP to HTTP and return any reply
 local rest_url = module:get_option_string("rest_callback_url", nil);
 if rest_url then
+	local function get_url() return rest_url; end
+	if rest_url:find("%b{}") then
+		local httputil = require "util.http";
+		local render_url = require"util.interpolation".new("%b{}", httputil.urlencode);
+		function get_url(stanza)
+			local at = stanza.attr;
+			return render_url(rest_url, { kind = stanza.name, type = at.type, to = at.to, from = at.from });
+		end
+	end
 	local send_type = module:get_option_string("rest_callback_content_type", "application/xmpp+xml");
 	if send_type == "json" then
 		send_type = "application/json";
 	end
 
 	module:set_status("info", "Not yet connected");
-	http.request(rest_url, {
+	http.request(get_url(st.stanza("meta", { type = "info", to = module.host, from = module.host })), {
 			method = "OPTIONS",
 		}, function (body, code, response)
 			if code == 0 then
@@ -455,7 +464,7 @@
 		stanza = st.clone(stanza, true);
 
 		module:log("debug", "Sending[rest]: %s", stanza:top_tag());
-		http.request(rest_url, {
+		http.request(get_url(stanza), {
 				body = request_body,
 				headers = {
 					["Content-Type"] = send_type,