Egg.js 中使用 egg-http-proxy 实现 Dify API 的 SSE 流式输出
在基于 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;
关键配置说明:
streaming: true启用流式传输模式headers中添加 Dify API 所需的认证头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);
}
}
});
注意事项
-
文件上传处理:如果需要使用 Dify 的文件上传接口,必须配置
egg-multipart的 mode 为 stream,否则会返回 400 错误。 -
错误处理:SSE 流可能会包含非 JSON 格式的数据,客户端需要妥善处理解析异常。
-
连接管理:使用 AbortController 可以灵活控制 SSE 连接的开启和关闭。
-
性能考虑:长时间保持的 SSE 连接会占用服务器资源,需要合理设计连接超时和重连机制。
总结
通过 Egg.js 的 egg-http-proxy 中间件,我们可以轻松实现 Dify API 的代理和 SSE 流式输出功能。这种方案既保持了 Egg.js 应用的架构完整性,又能充分利用 Dify 平台的流式聊天能力。在实际应用中,开发者可以根据业务需求进一步优化错误处理和连接管理逻辑。
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
jiuwenclawJiuwenClaw 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。Python0209- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
AtomGit城市坐标计划AtomGit 城市坐标计划开启!让开源有坐标,让城市有星火。致力于与城市合伙人共同构建并长期运营一个健康、活跃的本地开发者生态。01
MarkFlowy一款 AI Markdown 编辑器TSX01