更新记录

1.0.0(2026-07-28)

  • 首次发布跨端 SSE UTS API,支持 Android、iOS、HarmonyOS NEXT 与微信小程序。
  • 支持标准 SSE 解析、安全重连、POST 幂等恢复及 OpenAI/Anthropic 数据解析。
  • 提供稳定错误码与本地脱敏诊断,不上传业务数据。

平台兼容性

uni-app(5.15)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Safari app-vue app-vue插件版本 app-nvue app-nvue插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本
1.0.0 1.0.0 × × 1.0.0 1.0.0 5.0 1.0.0 12 1.0.0 1.0.0
微信小程序 微信小程序插件版本 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
1.0.0 - - - - - - - - - - -

uni-app x(5.15)

Chrome Safari Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本 微信小程序 微信小程序插件版本
× × 5.0 1.0.0 12 1.0.0 1.0.0 1.0.0

Longde SSE · 原生流式通信

longde-sse 是面向 AI 对话与实时推送的跨端 SSE UTS 插件,适用于 uni-app 与 uni-app x。它提供标准 SSE 协议解析、安全重连、POST 幂等恢复、AI 数据帧辅助解析和可复制的脱敏诊断。

核心能力

  • GET、POST 与其他自定义 HTTP 方法
  • 自定义请求头和 UTF-8 请求体
  • 标准 SSE dataeventidretry 字段解析
  • 多行 data 合并、注释/心跳忽略
  • UTF-8 字节分片、BOM 与 CR/LF/CRLF 边界处理
  • HTTP 状态码与响应头回调
  • 主动取消、连接超时、读取超时
  • GET/HEAD 可选自动重连、指数退避与 Last-Event-ID 续传
  • POST 显式幂等键保护下的可选自动恢复
  • 安全的同源/跨源重定向策略与 HTTPS 降级保护
  • Cookie 默认隔离,可显式启用会话 Cookie
  • 事件类型过滤、重连随机抖动与连接状态查询
  • 手动暂停/恢复,以及宿主驱动的断网和前后台恢复
  • OpenAI-compatible、Anthropic 与原始 AI 数据帧辅助解析,思考增量与最终回答分离
  • 不保存请求内容,不内置任何服务端密钥

安装

将插件目录放入项目:

uni_modules/longde-sse

UTS 插件的运行和原生编译需要 HBuilderX。Android 与 iOS 原生实现不依赖第三方 SDK。

平台与宿主

建议使用 HBuilderX 5.15+。插件支持 Android、iOS、HarmonyOS NEXT、微信小程序,以及 uni-app Vue 2、Vue 3 和 uni-app x。

宿主与平台 支持情况 使用说明
uni-app Vue 2/3 + Android/iOS 支持 通过 UTS 原生传输实现。
uni-app x + Android/iOS 支持 支持 VDOM;iOS 还支持 Vapor。
uni-app x + HarmonyOS NEXT 支持 采用 ArkTS 适配;Cookie、重定向和 HTTP 状态能力以运行时能力快照为准。
uni-app x + 微信小程序 支持 采用分块请求适配;需配置 HTTPS 和微信合法 request 域名。
Web 与其他小程序 不支持 -

付费 UTS 插件在 HarmonyOS NEXT 或微信小程序上使用时,需要 DCloud 云端编译,因此这两个目标当前要求 uni-app x 宿主。

当前版本已完成 Android 真机自动化、iOS 与 HarmonyOS NEXT 模拟器自动化,以及微信开发者工具的流式页面人工查看。iOS、HarmonyOS NEXT 与微信小程序尚未做真机验收;这不是功能限制,而是当前版本公开的验证边界。

从零开始使用

从插件目录导入 connect,传入 URL 和 onMessage 即可建立连接。connect() 立即返回一个 SSEClient,网络请求和参数校验都在异步流程中执行;因此请在 onError 中处理失败,而不是使用同步 try/catch 等待它抛错。

import { connect } from '@/uni_modules/longde-sse'

const client = connect({
  url: 'https://api.example.com/events',
  onMessage(event) {
    // event.data 是服务端一条完整 SSE data 内容
    console.log(event.event, event.id, event.data)
  },
  onError(error) {
    // 使用稳定数字 errCode 做业务分支;不要依赖 errMsg 文本。
    console.error(error.errCode, error.errMsg, error.data?.diagnosticId)
  },
  onClose(event) {
    console.log('closed:', event.reason)
  }
})

// 页面卸载、用户取消对话时调用;可重复调用。
client.close()

connect(options) 参数参考

urlonMessage 是必填项,其余均可省略。所有超时单位都是毫秒。请求头使用对象数组,不是普通对象,以便跨端保持一致的顺序和校验规则。

请求与诊断参数

参数 类型 默认值 / 范围 作用与格式
url string,必填 HTTP(S),最长 8192 字符 SSE 接口地址,例如 https://api.example.com/events。不支持 ws:、相对路径和空字符串。
method string GET,最长 32 字符 HTTP 方法,例如 GETPOST。必须是合法 HTTP token。
headers Array<{ name: string, value: string }> 无,最多 64 项 请求头,例如 [{ name: 'Authorization', value: 'Bearer xxx' }]。名称大小写不敏感且不能重复,名称和值不能含换行符。
body string UTF-8 请求体,通常为 JSON.stringify(...) 的结果。GETHEAD 会忽略它。插件不会记录该内容。
connectTimeout number 15000;1–120000 从发起请求到收到 HTTP 响应的最长等待时间。
readTimeout number 0;或 1000–86400000 已连接后两次收到网络字节之间的最长等待时间;0 表示不设读取超时,适合长期 SSE。
diagnosticsMaxEvents number 200;1–200 当前 client 在内存中保留的脱敏诊断事件数量;不是日志上传开关。
eventTypes Array<string> 不传或 [] 为全部;最多 32 项 仅派发指定的 SSE event: 类型,例如 ['message', 'delta']

自动重连与 POST 恢复

默认不重连GET/HEAD 设置 reconnect: true 后可使用下表策略。POST 可能有副作用或产生 AI 计费,必须同时设置 reconnectPost: true 与稳定的 idempotencyKey,并由服务端按该键去重。

参数 类型 默认值 / 范围 作用
reconnect boolean false 是否启用自动重连。未开启时连接断开即结束。
reconnectMaxRetries number 3;0–10 首次连接之后最多额外尝试多少次;0 表示不再尝试。
reconnectInitialDelay number 1000;100–60000 第一次重连前的等待时间。
reconnectMaxDelay number 30000;不小于初始值、最多 300000 指数退避等待时间的上限。
reconnectBackoffFactor number 2;1–4 每次等待的乘数;例如 2 为 1 秒、2 秒、4 秒。
reconnectJitterRatio number 0;0–1 等待时间的随机浮动比例;0.2 代表最多上下浮动 20%,用于避免集中重连。
reconnectUseServerRetry boolean false 是否采用服务端 SSE retry: 字段;开启后等待时间至少为 100ms。
reconnectOnEof boolean false 服务端正常关闭流(EOF)后是否也重连。
reconnectWithLastEventId boolean false 是否维护服务端 id: 并在重连时发送 Last-Event-ID
reconnectPost boolean false 显式允许 POST 自动重试;仅与 reconnectidempotencyKey 同时使用才有效。
idempotencyKey string 1–256 字符 POST 重试的稳定请求键;同一次业务请求必须固定,例如 chat- 加本次请求 UUID。
idempotencyHeader string Idempotency-Key 向服务端发送幂等键所使用的 Header 名称。

安全、重定向、Cookie 与生命周期参数

参数 类型 默认值 / 范围 作用
redirectPolicy 'never' \| 'same-origin' \| 'always' 'same-origin' 重定向策略:拒绝全部、仅同源、或允许跨源。非 GET/HEAD 只接受 307/308,避免请求体或方法被改写。
maxRedirects number 5;0–10 最多允许的跳转次数。
allowInsecureRedirect boolean false 是否允许 HTTPS 降级跳转到 HTTP;生产环境不建议开启。
allowCrossOriginSensitiveHeaders boolean false 跨源跳转时是否仍携带敏感 Header;默认会移除 AuthorizationCookieProxy-Authorization
sensitiveHeaders Array<string> 无,最多 32 项 除内置敏感 Header 外,还要在跨源跳转时移除的名称,例如 ['X-Api-Key']
cookiePolicy 'omit' \| 'include' 'omit' 默认不读写 Cookie;include 才启用当前 client 的会话 Cookie。请先用 getCapabilities() 确认平台支持程度。
pauseOnNetworkLoss boolean false 宿主调用 notifyNetworkChange(false) 时是否暂停。
resumeOnNetworkAvailable boolean false 网络恢复通知到来时,是否恢复因断网暂停的连接。
pauseOnBackground boolean false 宿主调用 notifyAppBackground() 时是否暂停。
resumeOnForeground boolean false 回到前台通知到来时,是否恢复因后台暂停的连接。

回调参数与数据结构

回调 触发时机 参数结构
onOpen(event) 收到合法 2xx SSE 响应后;每次成功重连也会触发 statusCodeheaders: SSEHeader[]urlredirectCountoperationIdreconnectCount
onMessage(event) 每条包含 data: 的完整 SSE 事件;必填 data(已合并多行 data)、event(未设置时为 message)、id: string \| nullretry: number \| null
onReconnect(event) 已决定重连、等待开始前 attempt(从 1 开始)、delaytriggerlastEventIdoperationId
onError(error) 参数错误、不可恢复的网络/HTTP/协议错误;最多一次 errCodeerrMsg,以及 error.datadiagnosticIdoperationIdstageretryablestatusCodenativeCode
onClose(event) 连接最终结束;最多一次 cancelledreasoncancelled / eof / no-content / failed)、stateoperationId

回调顺序为:成功连接时 onOpen → 零到多次 onMessageonClose;失败时 onErroronClose。HTTP 非 2xx 或错误 Content-Type 不会触发 onOpen

SSEClient 方法参考

方法 返回值 用法
close() void 取消当前请求及等待中的重连,最终关闭原因是 cancelled;可重复调用。
pause() / resume() void 暂停当前尝试但不产生最终 onCloseresume() 创建新的连接尝试。
notifyNetworkChange(isConnected) void 将宿主网络变化传给 client;需配合网络暂停/恢复开关。
notifyAppBackground() / notifyAppForeground() void 将宿主前后台变化传给 client;需配合前后台暂停/恢复开关。
getState() 状态字符串 返回 connectingopenreconnectingpausedclosingclosedfailed
isClosed() boolean closedfailed 返回 true
getOperationId() string 获取本次 client 生命周期固定的追踪 ID。
getReconnectCount() / getLastEventId() number / string \| null 获取已重连次数和最近服务端事件 ID。
getLastErrorCode() / getLastCloseReason() 错误码或关闭原因 / null 获取最终错误码或关闭原因。
getNextReconnectDelay() number \| null 重连等待中返回计划延迟,否则返回 null
getCurrentUrl() string 获取当前请求 URL。
getDiagnosticReport() / clearDiagnostics() string / void 导出或清空仅存在内存中的脱敏诊断;不会自动上传。

平台能力检测

调用 getCapabilities() 后再启用 Cookie、重定向或后台连接等依赖平台的策略。它返回 platformandroid / ios / harmony / mp-weixin)、streamingpostStreaminglastEventIdbackgroundStreaming,以及 reconnectcookiePolicyredirectPolicyhttpStatus 的支持等级。

import { getCapabilities } from '@/uni_modules/longde-sse'

const capabilities = getCapabilities()
if (capabilities.cookiePolicy !== 'native') {
  // 改用无 Cookie 的 Bearer Token,或禁用依赖会话 Cookie 的入口。
}

AI 流式对话示例

import { connect } from '@/uni_modules/longde-sse'

const requestId = 'chat-' + Date.now().toString()
const client = connect({
  url: 'https://example.com/v1/chat/completions',
  method: 'POST',
  headers: [
    { name: 'Authorization', value: 'Bearer ' + token },
    { name: 'Content-Type', value: 'application/json' }
  ],
  body: JSON.stringify({
    model: 'your-model',
    stream: true,
    messages: [{ role: 'user', content: '你好' }]
  }),
  onOpen(event) {
    console.log('SSE connected', event.statusCode)
  },
  onMessage(event) {
    if (event.data == '[DONE]') {
      client.close()
      return
    }
    console.log('chunk', event.data)
  },
  onError(error) {
    const data = error.data
    console.error(error.errCode, error.errMsg, data?.diagnosticId)
  },
  onClose(event) {
    console.log('SSE closed', event.reason)
  },
  // POST 重试必须与服务端幂等去重配合;不需要恢复时不要开启。
  reconnect: true,
  reconnectPost: true,
  idempotencyKey: requestId,
  reconnectMaxRetries: 2
})

推荐由业务后端持有 AI 服务密钥,App 连接自己的后端 SSE 接口。不要把长期有效的服务端密钥写进客户端代码。

parseOpenAICompatibleData(event.data) 可直接取得 kind/text/reasoning/done/metadata/invalid-json/raw;Anthropic 使用 parseAnthropicData,私有协议使用 parseRawAIDatareasoning 仅用于展示模型思考增量,不能混入最终回答或下一轮上下文。这些函数是无状态解析器,不会改变 SSE 连接、重连和诊断行为。

行为约定

  • 默认请求方法为 GET
  • 默认建连超时为 15 秒。
  • 默认读取超时为 0,即允许长连接一直等待下一条数据。
  • 只有包含至少一个 data 字段的事件才触发 onMessage
  • 服务端正常结束时 onClose.reasoneof;HTTP 204 为 no-content;主动关闭时为 cancelled
  • 自动重连默认关闭;GET/HEAD 可通过 reconnect: true 启用,其余策略使用 reconnectMaxRetries 等顶层字段。POST 只有同时启用 reconnectPost 并提供稳定 idempotencyKey 才允许重试,且服务端必须按该键去重。
  • 自动重连会处理网络错误、超时、HTTP 429/5xx 和可选 EOF,支持服务端 retry:Last-Event-ID 续传。
  • client.getState() 返回 connecting/open/reconnecting/paused/closing/closed/failedclose() 可重复调用。
  • pause() 取消当前请求但不终结 client,resume() 重新连接;网络与前后台通知均需宿主接入,自动暂停/恢复开关默认关闭。
  • 可查询最后错误、关闭原因、当前 URL 和下一次重连等待。
  • 启用重连后状态还可能为 reconnectingclose() 会同时取消等待中的重连。
  • client.getDiagnosticReport() 可导出仅在内存中保存的脱敏诊断 JSON,插件不会自动上传。
  • 单行上限为 256 KiB,单事件上限为 1 MiB;越界返回 7002,防止异常服务端无限占用内存。
  • event.retry 是服务端最新的合法重连提示;只有显式启用自动重连时才会用于下一次等待时间。

错误码与排查

错误对象的 errSubject 固定为 longde-sse::connecterror.data 中可取得不含密钥和正文的 diagnosticId,可随问题描述发送至 longdecloud@163.com 协助排查。插件不会自动上传诊断信息。

errCode 名称 含义与建议
1001 INVALID_URL URL 为空、过长或不是 HTTP(S),请修正参数。
1002 INVALID_METHOD HTTP 方法不合法,请修正参数。
1003 INVALID_HEADER 请求头数量、名称、值或重复项不合法。
1004 INVALID_TIMEOUT 建连或读取超时配置无效。
1005 INVALID_DIAGNOSTICS 诊断缓冲区事件数配置无效。
1006 INVALID_RECONNECT 自动重连、退避或 Last-Event-ID 配置无效。
1007 INVALID_TRANSPORT_POLICY 重定向、Cookie、敏感请求头或事件过滤策略无效。
1008 CAPABILITY_UNSUPPORTED 当前平台不支持所请求的能力组合;请先调用 getCapabilities() 调整策略。
4001 INVALID_NATIVE_RESPONSE 原生桥接响应无效;请导出诊断后反馈。
5001 HTTP_ERROR 服务端返回非 2xx;429 和 5xx 可按业务策略重试。
5002 NETWORK_ERROR DNS、TLS、断网或系统 I/O 失败。
5003 CONNECT_TIMEOUT 收到 HTTP 响应前超时。
5004 READ_TIMEOUT 已建立响应后等待后续字节超时。
5005 REDIRECT_ERROR 跳转被策略拒绝、地址无效或次数超限。
7001 INVALID_CONTENT_TYPE 响应不是 text/event-stream
7002 PARSE_ERROR SSE 单行或单事件超过安全上限等解析失败。
9001 INTERNAL_ERROR 未分类原生错误;请导出诊断后反馈。

“可重试”只表示传输层可能恢复。对 AI 的 POST 流,请使用请求幂等键和服务端去重,避免重复生成或重复计费。

隐私说明

插件仅向调用方传入的 URL 发起请求。请求头、请求体与流式响应仅在本次连接的内存中处理,不会被插件另行收集、持久化或上传。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android 需要 android.permission.INTERNET 网络权限;iOS、HarmonyOS NEXT 与微信小程序不申请额外敏感系统权限。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件仅将调用方提供的 URL、请求头和请求体发送到调用方指定的服务地址,用于建立 SSE 流式通信;流式响应仅在当前连接内存中处理。插件不收集、不存储、不向作者服务器上传任何数据,不包含第三方统计或网络 SDK。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。