Dify HTTP 请求节点实战:发送 JSON、解析响应与处理异常

工作流已经能提取任务、输出 JSON,下一步通常就是调用接口:把结果交给其他服务,再根据响应决定后续流程。

实际配置时,几个小问题就可能让流程卡住:请求体被重复编码,接口返回 HTML 却被当作 JSON 解析,或者 503 响应在进入条件判断之前就触发了节点失败。

本文用一个无鉴权的回显接口,完整走通 JSON 请求体构造 → HTTP 调用 → 状态码判断 → 响应解析 → 统一输出。示例数据和代码都在正文中,可独立完成练习。

1. 环境和本次目标

项目 本文使用的环境
Dify 社区版 1.17.1,自部署
部署方式 Docker Compose
操作系统 macOS / Windows,以下配置在浏览器中完成
应用类型 Workflow,由用户输入启动
演示接口 https://httpbin.org/anything
是否需要模型和 API Key 本篇不使用 LLM,演示接口无需鉴权

资料核对日期:2026-10-21。本文涉及的状态码、重试和异常处理行为按 Dify 1.17.1 说明,其他版本应结合实际节点行为验证。

httpbin 是 HTTP 请求与响应演示服务,/anything 会回显请求内容。我们只发送下文的虚构数据,核对 POST 方法和服务端解析到的 JSON 对象;回显成功不代表已经创建任务或完成业务写入 。httpbin 官方接口定义

2. 先看工作流结构

创建 Workflow,命名为"JSON 接口调用演示",按下面的结构编排:

text 复制代码
用户输入 → 准备请求体 → HTTP 回显 → 状态码判断
                                   ├─ 2xx → 校验回显 ─┐
                                   └─ 其他 → 状态提示 ─┤
                                                     ↓
                                                  结果汇合
                                                     ↓
                                                    输出

其中"准备请求体"和"校验回显"使用 Code 节点,"状态提示"使用 Template,"结果汇合"使用 Variable Aggregator。

本篇不再调用模型生成数据,便于先把接口链路单独调通。以后接回结构化提取流程时,可以直接使用已经校验过的对象。

3. 输入示例 JSON,构造请求体

3.1 用户输入字段

在用户输入节点(部分界面称 Start / 开始)中添加:

字段 设置
变量名称 payload_json
展示名称 待发送 JSON
类型 Paragraph / 段落
必填 是

试运行时使用以下完整示例:

json 复制代码
{
  "summary": "团队确认更新账号申请说明,并整理常见问题清单。",
  "action_items": [
    {
      "task": "更新账号申请说明,补充入口与字段",
      "owner": "王宁",
      "deadline": "2026-10-23",
      "evidence": "王宁负责在 2026-10-23 前更新账号申请说明。"
    },
    {
      "task": "整理账号申请常见问题清单",
      "owner": "",
      "deadline": "",
      "evidence": "团队决定整理常见问题清单,但负责人和完成时间未明确。"
    }
  ],
  "pending_notes": ["常见问题清单的负责人和完成时间待确认。"]
}

3.2 Code 节点:准备请求体

新增 Python Code 节点,命名为"准备请求体"。

  • 输入 payload_json:绑定"用户输入 → payload_json"。
  • 输出 request_body:String。
  • 删除不使用的默认输入、输出字段。
python 复制代码
import json


def main(payload_json: str) -> dict:
    if not isinstance(payload_json, str) or not payload_json.strip():
        raise ValueError("请提供 JSON 对象文本")
    try:
        payload = json.loads(payload_json)
    except json.JSONDecodeError:
        raise ValueError("输入不是合法 JSON,请检查引号、逗号和括号") from None
    if not isinstance(payload, dict):
        raise ValueError("请求内容必须是 JSON 对象")
    if not isinstance(payload.get("summary"), str):
        raise ValueError("summary 必须是字符串")
    if not isinstance(payload.get("action_items"), list):
        raise ValueError("action_items 必须是数组")
    if not isinstance(payload.get("pending_notes"), list):
        raise ValueError("pending_notes 必须是数组")
    return {
        "request_body": json.dumps(payload, ensure_ascii=False, allow_nan=False)
    }

json.loads 把输入文本解析为对象,json.dumps 再把对象序列化成可发送的 JSON 文本。中文、引号、换行等转义由序列化器处理,不需要手工拼接。

这段代码只检查本篇演示所需的基本结构。如果前面已经有业务字段校验,应继续保留,不要用这里的基础检查替代完整校验。

**接入已有对象时:**将 Code 的输入改为 data,绑定上游已校验的对象,序列化时使用 json.dumps(data, ensure_ascii=False, allow_nan=False) 即可,不需要再次 json.loads(data)。

4. HTTP 请求节点怎么填

添加 HTTP Request,命名为"HTTP 回显",连接"准备请求体"。配置如下:

配置项 本文取值
Method POST
URL https://httpbin.org/anything
Authorization No Auth
Header Content-Type: application/json
Body 类型 Raw Text / raw
Body 内容 仅插入"准备请求体 → request_body"变量
SSL Verification 保持开启
Retry 关闭
Error Handling None / 不处理异常

HTTP 节点可配置 URL、请求头、请求体和连接、读取、写入超时。官方 HTTP 节点说明

4.1 请求体只插入一次,不再加引号

打开 Raw 编辑区,通过变量选择器插入 request_body。整个请求体就是这个变量,外面不要再包一对引号,也不要加一个额外的 payload 对象。

Raw 模式会把变量替换后的文本作为请求内容发送;手动填写的 Content-Type: application/json 指明内容类型。官方请求体实现

例如,应该发送的是对象:

json 复制代码
{"summary":"示例","action_items":[],"pending_notes":[]}

如果再次对整段文本编码,发送的就可能变成一个 JSON 字符串:

json 复制代码
"{\"summary\":\"示例\",\"action_items\":[],\"pending_notes\":[]}"

这两种内容都可能符合 JSON 语法,但类型不同。后面的回显检查会识别这种错误。

4.2 为什么本文要求关闭 Retry

这是本篇最需要注意的版本细节。

Dify 1.17.1 的 HTTP 节点默认配置开启重试。该版本运行时在启用重试或异常处理策略时,会把非 2xx 响应按失败处理,未必进入下游的普通状态码判断。1.17.1 默认配置、官方运行时状态处理

本篇为了直接判断真实响应,采用固定模式:

Retry 关闭 + Error Handling 为 None → 收到的非 2xx 状态可沿普通路径交给条件节点判断。

网络断开、域名解析失败、连接或读取超时,则仍会导致节点失败;它们不等于"收到一个非 2xx 响应"。

5. 先判断状态,再解析正文

HTTP 节点的常用输出包括:

变量 类型 用途
status_code Number 判断 HTTP 状态
body String 响应正文,确认内容格式后再解析
headers Object 响应头

即便响应内容是 JSON,body 在这里仍是字符串,不能直接把它当成已经解析的业务对象。

在 HTTP 后添加 If/Else,命名为"状态码判断",用 AND 组合两个条件:

  1. "HTTP 回显 → status_code"大于等于数值 200。
  2. "HTTP 回显 → status_code"小于数值 300。

IF 进入成功分支,ELSE 进入状态提示分支。错误响应可能是空正文或 HTML,所以不要在分支之前无条件对 body 执行 JSON 解析。

6. 成功分支:解析并核对回显

IF 分支添加 Python Code,命名为"校验回显"。

输入绑定:

输入名称 来源
status_code HTTP 回显 → status_code
body HTTP 回显 → body
request_body 准备请求体 → request_body

只声明两个输出:report: String、echoed: Object。

python 复制代码
import json


def main(status_code: int, body: str, request_body: str) -> dict:
    if not 200 <= status_code < 300:
        raise ValueError("本节点只处理 2xx 成功分支")
    try:
        response = json.loads(body)
        expected = json.loads(request_body)
    except (json.JSONDecodeError, TypeError):
        raise ValueError("响应正文或请求体不是可解析的 JSON") from None
    if not isinstance(response, dict) or response.get("method") != "POST":
        raise ValueError("未收到预期的 POST 回显响应")
    echoed = response.get("json")
    if not isinstance(echoed, dict):
        raise ValueError("回显 json 不是对象,请检查请求体是否被重复编码")
    options = {"ensure_ascii": False, "sort_keys": True, "allow_nan": False}
    if json.dumps(echoed, **options) != json.dumps(expected, **options):
        raise ValueError("回显对象与发送的对象不一致")

    report = "\n".join([
        "# 接口回显核对",
        "",
        f"- HTTP 状态码:{status_code}",
        "- 请求方法:POST",
        "- 回显对象与请求对象:一致",
        "- 本次仅验证数据传输与回显,没有创建业务任务。",
        "",
        "## 回显数据",
        "",
        "```json",
        json.dumps(echoed, ensure_ascii=False, indent=2, allow_nan=False),
        "```",
    ])
    return {"report": report, "echoed": echoed}

httpbin 的回显对象中,method 表示收到的请求方法,json 表示服务端解析请求正文后的值。代码会检查方法、对象类型,以及回显对象与请求对象是否一致。httpbin 端点实现

核对成功时,report 包含可读说明,echoed 保留对象供后续使用。这里的成功条件专门针对本篇回显接口;换成真实业务 API 后,应按该 API 的响应结构判断。

7. 非 2xx 分支:给出明确状态提示

ELSE 分支添加 Template,命名为"状态提示"。新增本地输入变量 status_code,绑定"HTTP 回显 → status_code",模板填写:

jinja2 复制代码
# 接口调用状态

收到 HTTP {{ status_code }},本次未执行成功回显校验。

请查看 HTTP 节点的响应正文与响应头,并按接口文档判断错误原因。
当前结果不能用来确认业务操作已经成功。

不要把所有错误都写成"服务不可用",也不要仅凭一个错误状态就断言真实业务一定没有写入。不同接口的错误含义和事务行为,应以其文档为准。

汇合并输出

添加 Variable Aggregator,命名为"结果汇合",保持 Aggregation Group 关闭,选择两个字符串候选:

  • 校验回显 → report。
  • 状态提示 → output。

最后连接一个 Output,新增 report,绑定"结果汇合 → output"。互斥分支每次只运行其中一条,聚合器提供统一输出。官方变量聚合器说明

8. 验证成功、状态错误和超时

8.1 正常回显

使用 /anything 和正文示例完整运行,预期检查:

  • 请求方法为 POST。
  • Content-Type 是 application/json。
  • 状态判断进入 2xx 分支。
  • 回显 json 是对象,且与发送对象一致。
  • 报告明确表述"传输与回显通过",没有声称创建业务任务。

8.2 模拟 503 响应

暂时把 URL 改为:

text 复制代码
https://httpbin.org/status/503

保持 Retry 关闭、Error Handling 为 None。若接口按定义返回 503,预期走 ELSE,显示真实状态码,不进入成功正文解析。完成后将 URL 改回 /anything。httpbin 状态码接口定义

8.3 区分超时和 HTTP 错误

连接、读取、写入超时分别对应不同阶段,可在节点高级设置中配置。练习时可按界面单位先设置连接 5 秒、读取 20 秒、写入 20 秒;这些是演示取值,应根据实际接口调整。

若需观察读取超时,可在测试环境尝试 httpbin 的 /delay/5,并把读取超时临时改为 1 秒。公共服务、缓存和代理会影响表现,应以节点实际错误为准,不能把它当作精确计时基准。

本篇模式下,超时会导致流程失败,而不是得到一个可判断的真实响应状态。不要人为填 200、0 或其他数字,把它包装成正常 HTTP 结果。

8.4 如果想让网络错误也显示友好提示

可以另行启用 HTTP 的异常分支,将它连接到失败提示节点。但要同时调整原来的预期:在 1.17.1 中,启用异常处理后,非 2xx 响应也会进入失败路径,不能继续期待普通 ELSE 分支拿到它们。

因此要先选定处理模式,再配置连线:

模式 主要用途
本文模式:重试关闭、异常处理 None 直接拿真实状态码,判断收到的响应
异常分支模式 将非 2xx 与网络类失败统一接入失败路径

不要给失败路径配置一个虚假的成功状态作为默认值。

9. 接入真实 API 前,要改哪些地方

项目 需要按真实接口调整的内容
URL 和方法 接口地址,以及 GET、POST 等实际约定
请求体 字段名称、必填项、类型和业务校验
认证 将密钥放入 Secret 类型环境变量,按文档配置认证
响应解析 修改成功分支,不再固定读取 httpbin 的 method、json
成功判断 除 HTTP 状态外,核对业务状态、业务 ID 等实际约定
重试 对可能产生写入的请求,先确认幂等机制和重复提交处理

真实密钥不应被放入普通用户输入、示例 JSON 或公开回显请求中。配置认证时,可通过变量选择器引用 Secret 环境变量;本例仍保持 No Auth。Dify HTTP 认证与变量说明

请求超时只表示调用方未及时拿到结果,不等于服务端一定没有执行。对于真实创建类接口,是否可以重试,应依据服务端幂等和结果查询机制决定。

10. 常见问题排查表

现象 优先检查
接口说 JSON 格式不对 请求体是否只插入 request_body,是否重复加引号
回显 json 是字符串 是否对已序列化的请求体再次 JSON 编码
响应解析提示正文不是 JSON 是否先判断了状态,实际 body 是否为 HTML 或空文本
503 没有进入 ELSE Retry 是否关闭,Error Handling 是否为 None
浏览器能访问,Dify 请求失败 Dify 容器的网络、代理、DNS 和证书链是否可用
Code 输出字段报错 声明的名称和类型是否与返回字典一致
响应状态成功,但回显核对失败 对象是否被包装、截断或修改,URL 是否仍为演示接口
聚合器变量不匹配 两个候选是否都是字符串,是否误开聚合分组

先在节点调试中定位输入与输出,再执行完整试运行;发布当前配置后,还要从 Web App 页面重新验证。

11. 验证范围与参考资料

本文的请求构造、响应解析代码使用本地示例与模拟响应检查。完整 Dify 工作流未在本文环境中实机运行;公网回显请求检查因本地执行环境的域名解析限制未完成,因此没有把公开服务可达性写成实测结论。

完整复现时,仍需在自己的 Dify 环境确认网络连通、节点运行、两条正常分支及超时行为。公开演示服务的实时可用性不属于本文代码保证范围。

参考资料:

后续可以把这条链路接到真实任务接口:先校验结构化数据,再按接口要求构造请求,最后根据业务响应确认结果。每一步都有明确输入和输出,才便于定位问题和维护。

相关推荐
ITxiaobing20235 小时前
海外广告投放的 IP 定位服务怎么选?一份基于实测数据的选型参考
网络协议·tcp/ip·php
cfm_29146 小时前
初步了解ECDHE密钥交换
http
Lsetea8 小时前
curl -I检查HTTPS返回405:HEAD、GET与证书验收分层排查
linux·http·https·ssl证书·curl
我命由我123458 小时前
Python 开发 - Python 虚拟环境
运维·开发语言·后端·python·http·https·java-ee
qq_白羊座9 小时前
口头说的 JSON 和 MySQL 里的 JSON
数据库·mysql·json
承渊政道9 小时前
Linux网络学习【传输层协议UDP】
linux·网络·网络协议·学习·ubuntu·udp
Chery11409 小时前
DPE5500 SPI以太网协议栈芯片详解:10/100M以太网、硬件TCP/IP与国产替代方案
arm开发·网络协议·tcp/ip
zxanz110 小时前
SSL 证书该怎么申请?操作复杂吗?
网络·网络协议·ssl
love静思冥想11 小时前
CLOB中JSON查询agent字段值(Oracle11g)
sql·oracle·json