diff --git a/package-lock.json b/package-lock.json index cdb20034c..04b4ea15b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "limiter": "~2.1.0", + "liquidjs": "^10.7.0", "mongodb": "~4.14.0", "mqtt": "~4.3.7", "mssql": "~8.1.4", @@ -13139,6 +13140,33 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/liquidjs": { + "version": "10.7.1", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.7.1.tgz", + "integrity": "sha512-tl9nWBZrrKcC61yfih3lbtSjAn+k7e0HhwydPjQKI4+metLk927HYBfXfbf6yrCcYjnBnLzk8xMjUF83yknAQQ==", + "dependencies": { + "commander": "^10.0.0" + }, + "bin": { + "liquid": "bin/liquid.js", + "liquidjs": "bin/liquid.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/liquidjs" + } + }, + "node_modules/liquidjs/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, "node_modules/listr2": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", diff --git a/package.json b/package.json index 7fc736000..ff5c0dc01 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "limiter": "~2.1.0", + "liquidjs": "^10.7.0", "mongodb": "~4.14.0", "mqtt": "~4.3.7", "mssql": "~8.1.4", diff --git a/server/notification-providers/webhook.js b/server/notification-providers/webhook.js index 649746b8e..9f5643b4e 100644 --- a/server/notification-providers/webhook.js +++ b/server/notification-providers/webhook.js @@ -1,6 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const FormData = require("form-data"); +const { Liquid } = require("liquidjs"); class Webhook extends NotificationProvider { @@ -15,17 +16,27 @@ class Webhook extends NotificationProvider { monitor: monitorJSON, msg, }; - let finalData; let config = { headers: {} }; if (notification.webhookContentType === "form-data") { - finalData = new FormData(); - finalData.append("data", JSON.stringify(data)); - config.headers = finalData.getHeaders(); - } else { - finalData = data; + const formData = new FormData(); + formData.append("data", JSON.stringify(data)); + config.headers = formData.getHeaders(); + data = formData; + } else if (notification.webhookContentType === "custom") { + // Initialize LiquidJS and parse the custom Body Template + const engine = new Liquid(); + const tpl = engine.parse(notification.webhookCustomBody); + + // Insert templated values into Body + data = await engine.render(tpl, + { + msg, + heartbeatJSON, + monitorJSON + }); } if (notification.webhookAdditionalHeaders) { @@ -39,7 +50,7 @@ class Webhook extends NotificationProvider { } } - await axios.post(notification.webhookURL, finalData, config); + await axios.post(notification.webhookURL, data, config); return okMsg; } catch (error) { diff --git a/server/server.js b/server/server.js index 976dca5de..c35af7fc1 100644 --- a/server/server.js +++ b/server/server.js @@ -208,6 +208,7 @@ let needSetup = false; }); if (isDev) { + app.use(express.urlencoded({ extended: true })); app.post("/test-webhook", async (request, response) => { log.debug("test", request.headers); log.debug("test", request.body); diff --git a/src/components/notifications/Webhook.vue b/src/components/notifications/Webhook.vue index 1b85a5409..4262ad067 100644 --- a/src/components/notifications/Webhook.vue +++ b/src/components/notifications/Webhook.vue @@ -12,61 +12,97 @@
-
- - +
+ + +
+
+ +
-
- -
diff --git a/src/lang/en.json b/src/lang/en.json index dc23e2ad8..21364d7c7 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -196,8 +196,11 @@ "Content Type": "Content Type", "webhookJsonDesc": "{0} is good for any modern HTTP servers such as Express.js", "webhookFormDataDesc": "{multipart} is good for PHP. The JSON will need to be parsed with {decodeFunction}", + "webhookCustomBodyDesc": "Define a custom HTTP Body for the request. Template variables {msg}, {heartbeat}, {monitor} are accepted.", "webhookAdditionalHeadersTitle": "Additional Headers", - "webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook.", + "webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook. Each header should be defined as a JSON key/value.", + "webhookBodyPresetOption": "Preset - {0}", + "webhookBodyCustomOption": "Custom Body", "Webhook URL": "Webhook URL", "Application Token": "Application Token", "Server URL": "Server URL", @@ -757,5 +760,6 @@ "Group": "Group", "Monitor Group": "Monitor Group", "noGroupMonitorMsg": "Not Available. Create a Group Monitor First.", - "Close": "Close" + "Close": "Close", + "Request Body": "Request Body" }