Ver Fonte

fix(http_request): send form data (#10431)

-LAN- há 5 meses atrás
pai
commit
438ad8148b

+ 9 - 13
api/core/workflow/nodes/http_request/executor.py

@@ -97,15 +97,6 @@ class Executor:
         headers = self.variable_pool.convert_template(self.node_data.headers).text
         self.headers = _plain_text_to_dict(headers)
 
-        body = self.node_data.body
-        if body is None:
-            return
-        if "content-type" not in (k.lower() for k in self.headers) and body.type in BODY_TYPE_TO_CONTENT_TYPE:
-            self.headers["Content-Type"] = BODY_TYPE_TO_CONTENT_TYPE[body.type]
-        if body.type == "form-data":
-            self.boundary = f"----WebKitFormBoundary{_generate_random_string(16)}"
-            self.headers["Content-Type"] = f"multipart/form-data; boundary={self.boundary}"
-
     def _init_body(self):
         body = self.node_data.body
         if body is not None:
@@ -154,9 +145,8 @@ class Executor:
                         for k, v in files.items()
                         if v.related_id is not None
                     }
-
                     self.data = form_data
-                    self.files = files
+                    self.files = files or None
 
     def _assembling_headers(self) -> dict[str, Any]:
         authorization = deepcopy(self.auth)
@@ -217,6 +207,7 @@ class Executor:
             "timeout": (self.timeout.connect, self.timeout.read, self.timeout.write),
             "follow_redirects": True,
         }
+        # request_args = {k: v for k, v in request_args.items() if v is not None}
 
         response = getattr(ssrf_proxy, self.method)(**request_args)
         return response
@@ -244,6 +235,13 @@ class Executor:
         raw += f"Host: {url_parts.netloc}\r\n"
 
         headers = self._assembling_headers()
+        body = self.node_data.body
+        boundary = f"----WebKitFormBoundary{_generate_random_string(16)}"
+        if body:
+            if "content-type" not in (k.lower() for k in self.headers) and body.type in BODY_TYPE_TO_CONTENT_TYPE:
+                headers["Content-Type"] = BODY_TYPE_TO_CONTENT_TYPE[body.type]
+            if body.type == "form-data":
+                headers["Content-Type"] = f"multipart/form-data; boundary={boundary}"
         for k, v in headers.items():
             if self.auth.type == "api-key":
                 authorization_header = "Authorization"
@@ -256,7 +254,6 @@ class Executor:
 
         body = ""
         if self.files:
-            boundary = self.boundary
             for k, v in self.files.items():
                 body += f"--{boundary}\r\n"
                 body += f'Content-Disposition: form-data; name="{k}"\r\n\r\n'
@@ -271,7 +268,6 @@ class Executor:
             elif self.data and self.node_data.body.type == "x-www-form-urlencoded":
                 body = urlencode(self.data)
             elif self.data and self.node_data.body.type == "form-data":
-                boundary = self.boundary
                 for key, value in self.data.items():
                     body += f"--{boundary}\r\n"
                     body += f'Content-Disposition: form-data; name="{key}"\r\n\r\n'

+ 69 - 0
api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py

@@ -196,3 +196,72 @@ def test_extract_selectors_from_template_with_newline():
     )
 
     assert executor.params == {"test": "line1\nline2"}
+
+
+def test_executor_with_form_data():
+    # Prepare the variable pool
+    variable_pool = VariablePool(
+        system_variables={},
+        user_inputs={},
+    )
+    variable_pool.add(["pre_node_id", "text_field"], "Hello, World!")
+    variable_pool.add(["pre_node_id", "number_field"], 42)
+
+    # Prepare the node data
+    node_data = HttpRequestNodeData(
+        title="Test Form Data",
+        method="post",
+        url="https://api.example.com/upload",
+        authorization=HttpRequestNodeAuthorization(type="no-auth"),
+        headers="Content-Type: multipart/form-data",
+        params="",
+        body=HttpRequestNodeBody(
+            type="form-data",
+            data=[
+                BodyData(
+                    key="text_field",
+                    type="text",
+                    value="{{#pre_node_id.text_field#}}",
+                ),
+                BodyData(
+                    key="number_field",
+                    type="text",
+                    value="{{#pre_node_id.number_field#}}",
+                ),
+            ],
+        ),
+    )
+
+    # Initialize the Executor
+    executor = Executor(
+        node_data=node_data,
+        timeout=HttpRequestNodeTimeout(connect=10, read=30, write=30),
+        variable_pool=variable_pool,
+    )
+
+    # Check the executor's data
+    assert executor.method == "post"
+    assert executor.url == "https://api.example.com/upload"
+    assert "Content-Type" in executor.headers
+    assert "multipart/form-data" in executor.headers["Content-Type"]
+    assert executor.params == {}
+    assert executor.json is None
+    assert executor.files is None
+    assert executor.content is None
+
+    # Check that the form data is correctly loaded in executor.data
+    assert isinstance(executor.data, dict)
+    assert "text_field" in executor.data
+    assert executor.data["text_field"] == "Hello, World!"
+    assert "number_field" in executor.data
+    assert executor.data["number_field"] == "42"
+
+    # Check the raw request (to_log method)
+    raw_request = executor.to_log()
+    assert "POST /upload HTTP/1.1" in raw_request
+    assert "Host: api.example.com" in raw_request
+    assert "Content-Type: multipart/form-data" in raw_request
+    assert "text_field" in raw_request
+    assert "Hello, World!" in raw_request
+    assert "number_field" in raw_request
+    assert "42" in raw_request