HTTP Request node: array[object] variables are inserted as Python repr, corrupting the request body

#43465 · closed · 2 comments

View on GitHub ↗

niansia

### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 1.17.1 (main at 8222397) ### Cloud or Self Hosted Self Hosted (Source) ### Steps to reproduce 1. Add a Code node with an output `items` of type `Array[Object]` that returns: ```json [{"sku": "A1", "gift": true, "note": null}, {"sku": "B2", "gift": false, "note": "Tom's"}] ``` 2. Add an HTTP Request node after it, body type `JSON`, body: ``` {"items": {{#code.items#}}} ``` 3. Run the workflow and check the request body that was sent. Same with a `raw-text` body, and with other `Array[Object]` values such as the Knowledge Retrieval `result`. Repro without the UI (run from `api/`): ```python import json from graphon.nodes.http_request.entities import HttpRequestNodeConfig, HttpRequestNodeData, HttpRequestNodeTimeout from graphon.nodes.http_request.executor import Executor from graphon.runtime.variable_pool import VariablePool items = [{"sku": "A1", "gift": True, "note": None}, {"sku": "B2", "gift": False, "note": "Tom's"}] pool = VariablePool() pool.add(["code", "items"], items) def build(body_type): node_data = HttpRequestNodeData.model_validate( { "title": "HTTP Request", "type": "http-request", "method": "post", "url": "https://example.com/orders", "authorization": {"type": "no-auth"}, "headers": "", "params": "", "body": {"type": body_type, "data": [{"type": "text", "key": "", "value": '{"items": {{#code.items#}}}'}]}, } ) return Executor( node_data=node_data, timeout=HttpRequestNodeTimeout(connect=10, read=60, write=60), variable_pool=pool, http_request_config=HttpRequestNodeConfig(10, 60, 60, 1 << 20, 1 << 20, True, 0), http_client=object(), file_manager=object(), ) print("json body: ", json.dumps(build("json").json)) print("raw-text body:", build("raw-text").content) ``` Output: ``` json body: {"items": [{"sku": "A1", "gift": true, "note": "None}, {'sku': 'B2', 'gift': False, 'note': \"Tom's\"}"}]} raw-text body: {"items": [{'sku': 'A1', 'gift': True, 'note': None}, {'sku': 'B2', 'gift': False, 'note': "Tom's"}]} ``` `ArraySegment.text` is just `str(self.value)`, i.e. a Python repr with single quotes, `True` and `None`: https://github.com/langgenius/graphon/blob/11e2dee8cbd6dc2e6bf1c2059d9bbf4d0437ebe5/src/graphon/variables/segments.py#L128-L134 Only `ArrayStringSegment` overrides it with `json.dumps` (that came from the #12809 fix): https://github.com/langgenius/graphon/blob/11e2dee8cbd6dc2e6bf1c2059d9bbf4d0437ebe5/src/graphon/variables/segments.py#L168-L177 The executor pastes `.text` into the body template. A JSON body then goes through `repair_json`, and a raw-text body is sent as is: https://github.com/langgenius/graphon/blob/11e2dee8cbd6dc2e6bf1c2059d9bbf4d0437ebe5/src/graphon/nodes/http_request/executor.py#L269-L287 #34185 made object and `Array[Object]` variables selectable in the HTTP body, but that was a frontend change only. langgenius/graphon#235 only covers string variables. ### ✔️ Expected Behavior The array is inserted as JSON and the API receives the same two objects. ### ❌ Actual Behavior With a JSON body, the second object ends up inside the first one's `note` as a string, and `null` becomes the string `"None"` (see the output above). With a raw-text body, the body isn't valid JSON at all. There's no error in either case, the request just goes out with the wrong data. Even a single null with no apostrophes, e.g. `[{"a": null}]`, is sent as `[{"a": "None"}]`.

Comments

leilei3167

Looking into this. The HTTP Request node inserts `Array[Object]` through the segment text, which is still a Python repr. `Array[String]` already serializes as JSON. I'll align the object-array segment the same way.

Stream29

Reproduced in a self-hosted Dify 1.17.1 workflow: inserting an `Array[Object]` variable into an HTTP Request JSON body produces invalid JSON. The screenshot shows the node's Test Run process data. We'll be working on this. <img width="500" height="835" alt="Image" src="https://github.com/user-attachments/assets/8029f24f-4b95-4703-b0e9-43fe55fdf380" />