Переглянути джерело

fix: Respond to Webhook makes content-type precedence explicit and fails loudly on a bad body path

A lowercase content-type entry in the extra headers config used to
survive alongside the canonical Content-Type header, and which one
reached the client came down to nlohmann's alphabetical key order
rather than intent. Now any case-variant of content-type is dropped
from the extra headers before the canonical one is set, so the
Content Type field always wins.

Also, bodySource: input used to resolve an unknown bodyField path to
undefined, which JSON.stringify silently drops from _webhookResponse,
so the caller got an empty body with no signal anything was wrong.
Now an undefined result throws, naming the path. A path resolving to
null is still sent as-is, since null is a legitimate value.
fszontagh 1 місяць тому
батько
коміт
86ec0b0adf

+ 11 - 1
nodes/core/respond-to-webhook.js

@@ -44,7 +44,7 @@ const configSchema = {
         headers: {
             type: 'object',
             title: 'Extra Headers',
-            description: 'Additional response headers',
+            description: 'Additional response headers. A content-type entry here is ignored; use the Content Type field above instead',
             additionalProperties: { type: 'string' }
         }
     }
@@ -80,6 +80,10 @@ async function execute(config, input, context) {
     let body;
     if (source === 'input') {
         body = smartbotic.utils.getFieldValue(input, config.bodyField || 'data');
+        if (body === undefined) {
+            throw new Error('Respond to Webhook: nothing found at "' +
+                (config.bodyField || 'data') + '" to send as the body');
+        }
     } else if (source === 'text') {
         body = config.body === undefined || config.body === null ? '' : String(config.body);
     } else {
@@ -99,6 +103,12 @@ async function execute(config, input, context) {
     const headers = {};
     if (config.headers && typeof config.headers === 'object') {
         for (const name of Object.keys(config.headers)) {
+            // A header named content-type in any casing would otherwise survive
+            // alongside the canonical one, and which of the two reaches the
+            // client would come down to key ordering rather than intent.
+            if (name.toLowerCase() === 'content-type') {
+                continue;
+            }
             headers[name] = String(config.headers[name]);
         }
     }

+ 14 - 0
tests/nodes/respond-to-webhook-errors.json

@@ -0,0 +1,14 @@
+{
+  "name": "verify-respond-to-webhook-errors",
+  "nodes": [
+    {"id": "n1", "name": "Start", "type": "click-trigger", "position": {"x": 0, "y": 0}, "config": {}},
+    {"id": "n2", "name": "Respond", "type": "respond-to-webhook", "position": {"x": 0, "y": 100},
+     "config": {"status": 200, "bodySource": "input", "bodyField": "data.doesNotExist"}}
+  ],
+  "connections": [
+    {"sourceNodeId": "n1", "sourceOutput": "main", "targetNodeId": "n2", "targetInput": "data"}
+  ],
+  "expect": {
+    "n2": {"status": "failed", "errorContains": "nothing found at \"data.doesNotExist\""}
+  }
+}