首页
/ Egg.js 中使用 egg-http-proxy 实现 Dify API 的 SSE 流式输出

Egg.js 中使用 egg-http-proxy 实现 Dify API 的 SSE 流式输出

2025-05-11 23:03:08作者:廉彬冶Miranda

在基于 Egg.js 框架开发应用时,我们经常需要代理第三方 API 接口。本文将详细介绍如何使用 egg-http-proxy 中间件来代理 Dify 平台的聊天消息接口,并实现 Server-Sent Events (SSE) 的流式输出功能。

技术背景

SSE (Server-Sent Events) 是一种服务器推送技术,允许服务器单向向客户端发送事件流。与 WebSocket 不同,SSE 是单向通信,适用于服务器向客户端推送数据的场景。Dify 平台的 /chat-messages 接口在 response_mode=streaming 参数下会返回 SSE 格式的聊天消息流。

服务端实现

在 Egg.js 项目中,我们需要创建一个控制器来处理 Dify API 的代理请求:

const Controller = require('egg').Controller;

class DifyController extends Controller {
  async all() {
    const { ctx, config } = this;

    await ctx.proxyRequest(config.dify.host, {
      streaming: true,  // 启用流式传输
      headers: {
        Authorization: 'Bearer ' + config.dify.apiKey,
      },
      rewrite(urlObj) {
        // 重写路径,移除/dify前缀
        urlObj.pathname = urlObj.pathname.replace(/^\/dify/, '');
        return urlObj;
      }
    });
  }
}

module.exports = DifyController;

关键配置说明:

  1. streaming: true 启用流式传输模式
  2. headers 中添加 Dify API 所需的认证头
  3. rewrite 函数用于重写请求路径

客户端实现

客户端需要使用 EventSource 或兼容的库来接收 SSE 事件流。这里我们使用 @microsoft/fetch-event-source 库:

import { fetchEventSource } from '@microsoft/fetch-event-source'

const ctrl = new AbortController();
let loading = 'Loading...';
let answer = '';

fetchEventSource('/chat-messages', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer {API_KEY}'
  },
  body: JSON.stringify({
    user: 'fym',
    query: 'Hello',
    response_mode: 'streaming',
    inputs: {}
  }),
  signal: ctrl.signal,
  onopen: (e) => {
    console.log('SSE连接已建立', e);
  },
  onclose: (e) => {
    console.log('SSE连接已关闭', e);
    loading = 'closed';
  },
  onerror: (e) => {
    console.error('SSE错误', e);
    loading = e.message;
    ctrl.abort();
  },
  onmessage: (e) => {
    try {
      const data = JSON.parse(e.data);
      loading = data.event;
      
      switch (data.event) {
        case 'message':
          answer += data.answer;
          break;
        case 'end':
          loading = '';
          break;
        case 'error':
          loading = data.error;
          ctrl.abort();
          break;
        default:
          break;
      }
    } catch (error) {
      // 忽略JSON解析错误,继续处理后续事件
      console.warn('SSE数据解析异常', error);
    }
  }
});

注意事项

  1. 文件上传处理:如果需要使用 Dify 的文件上传接口,必须配置 egg-multipart 的 mode 为 stream,否则会返回 400 错误。

  2. 错误处理:SSE 流可能会包含非 JSON 格式的数据,客户端需要妥善处理解析异常。

  3. 连接管理:使用 AbortController 可以灵活控制 SSE 连接的开启和关闭。

  4. 性能考虑:长时间保持的 SSE 连接会占用服务器资源,需要合理设计连接超时和重连机制。

总结

通过 Egg.js 的 egg-http-proxy 中间件,我们可以轻松实现 Dify API 的代理和 SSE 流式输出功能。这种方案既保持了 Egg.js 应用的架构完整性,又能充分利用 Dify 平台的流式聊天能力。在实际应用中,开发者可以根据业务需求进一步优化错误处理和连接管理逻辑。

登录后查看全文
热门项目推荐

项目优选

收起
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
179
263
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
869
514
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
130
183
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
295
331
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
333
1.09 K
harmony-utilsharmony-utils
harmony-utils 一款功能丰富且极易上手的HarmonyOS工具库,借助众多实用工具类,致力于助力开发者迅速构建鸿蒙应用。其封装的工具涵盖了APP、设备、屏幕、授权、通知、线程间通信、弹框、吐司、生物认证、用户首选项、拍照、相册、扫码、文件、日志,异常捕获、字符、字符串、数字、集合、日期、随机、base64、加密、解密、JSON等一系列的功能和操作,能够满足各种不同的开发需求。
ArkTS
18
0
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.07 K
0
kernelkernel
deepin linux kernel
C
22
5
WxJavaWxJava
微信开发 Java SDK,支持微信支付、开放平台、公众号、视频号、企业微信、小程序等的后端开发,记得关注公众号及时接受版本更新信息,以及加入微信群进行深入讨论
Java
829
22
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
601
58