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 平台的流式聊天能力。在实际应用中,开发者可以根据业务需求进一步优化错误处理和连接管理逻辑。
kernelopenEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。C081
baihu-dataset异构数据集“白虎”正式开源——首批开放10w+条真实机器人动作数据,构建具身智能标准化训练基座。00
mindquantumMindQuantum is a general software library supporting the development of applications for quantum computation.Python056
PaddleOCR-VLPaddleOCR-VL 是一款顶尖且资源高效的文档解析专用模型。其核心组件为 PaddleOCR-VL-0.9B,这是一款精简却功能强大的视觉语言模型(VLM)。该模型融合了 NaViT 风格的动态分辨率视觉编码器与 ERNIE-4.5-0.3B 语言模型,可实现精准的元素识别。Python00
GLM-4.7GLM-4.7上线并开源。新版本面向Coding场景强化了编码能力、长程任务规划与工具协同,并在多项主流公开基准测试中取得开源模型中的领先表现。 目前,GLM-4.7已通过BigModel.cn提供API,并在z.ai全栈开发模式中上线Skills模块,支持多模态任务的统一规划与协作。Jinja00
agent-studioopenJiuwen agent-studio提供零码、低码可视化开发和工作流编排,模型、知识库、插件等各资源管理能力TSX0135
Spark-Formalizer-X1-7BSpark-Formalizer 是由科大讯飞团队开发的专用大型语言模型,专注于数学自动形式化任务。该模型擅长将自然语言数学问题转化为精确的 Lean4 形式化语句,在形式化语句生成方面达到了业界领先水平。Python00