更新记录

1.0.1(2026-10-16)

  • 修复 Android 代理目标校验中可空 IP 地址与非空地址列表比较时的 Kotlin 类型警告,保留本监听器、环回地址与本机地址的代理防循环保护。
  • 同步 uni-app、uni-app x 的插件源码及示例诊断版本信息。

1.0.0(2026-10-15)

  • 建立本地 HTTP 服务的公共 UTS 接口、统一错误与三端原生适配。
  • 提供服务生命周期、动态接口、静态目录、流式文件传输、Range/缓存、安全控制、代理及实时通信业务模块。
  • 提供 uni-app / uni-app x 业务示例、局域网协作网页、完整诊断与固定快照分段复制。
  • 当前为本地开发候选,原生编译与设备验证范围见平台说明,不代表已上架发布。

平台兼容性

uni-app(5.26)

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

uni-app x(5.26)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × √ - √ -

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

lizhao-http-server

介绍

lizhao-http-server 是面向 uni-app / uni-app x 的本地 HTTP 服务 UTS 插件。让 App 在当前设备或局域网中提供网页、业务接口、文件传输和实时消息服务,适合离线使用、手机电脑协作以及设备与业务系统联动。

核心能力位于插件原生层:Android 使用 Kotlin 与系统网络/文件 API,iOS 使用 Swift 与 Network,HarmonyOS 使用 ArkTS 网络/文件 API。页面负责接入业务;大文件通过原生文件流传输。

功能特色

功能 能解决什么问题 对应能力
多服务管理 一个 App 分开提供网页、业务接口或媒体服务 创建、启动、停止、重启、销毁、状态查询
本机与局域网 离线网页在设备内打开,或让同网电脑访问 回环监听、显式 LAN、系统分配端口
动态业务接口 将设备状态或业务操作接入 HTTP 路由、路径参数、查询参数、JSON/文本/表单
静态站点 提供 HTML/CSS/JS/图片/PDF/WASM 等资源 多目录挂载、首页、可选 SPA 回退、MIME
文件下载与媒体 下载大文件、按区间读取、访问本地媒体 原生文件流、Range、HEAD、缓存验证
文件上传 电脑浏览器向 App 传文件 multipart、原始二进制、落盘与限额
分片续传 中断后从已接收偏移继续传输 会话、偏移查询、幂等分片、合并校验、取消
访问控制 按业务限制谁能访问、允许哪些跨域来源 Token/Basic、CORS、IP/Host、超时与容量限制
HTTPS 使用应用提供的证书身份保护传输 平台 TLS;身份与信任由应用配置
固定上游代理 将指定本地前缀转发到自己的服务器 流式转发、固定目标、超时、系统证书校验
实时通信 网页接收设备状态或与 App 双向通信 SSE、WebSocket、心跳、单播/广播、关闭
完整诊断 一次复现后取得可供排查的完整报告 原生快照、关联编号、脱敏、分段复制

具体平台能力和限制可通过 getServerCapabilities() 查询,平台及验证边界见本文“注意事项”中的平台与资源说明。本地服务按 HTTP/1.1 工作;视频播放效果还取决于播放器是否支持对应编码。

适合哪些场景

场景 推荐接入 你能得到什么
App 内离线 H5 回环服务 + 静态目录 + web-view 使用统一 HTTP 路径读取网页资源
手机与电脑传文件 LAN + 协作网页 + 上传/下载 同网络浏览器即可访问传输入口
工业设备/业务终端 动态路由 + 业务处理器 接收 HTTP 操作并返回真实业务结果
本地视频、音频和 HLS 文件响应或静态挂载 正确的 MIME、HEAD、Range 与分片访问
设备实时看板 SSE App 向已连接网页推送状态
双向控制与协作 WebSocket 消息、事件与连接生命周期
内网业务接入 固定上游代理 + 鉴权/TLS 将本地业务路径转到指定内网服务

下载与导入

  1. 保留完整 uni_modules/lizhao-http-server 目录,导入自己的 uni-app 或 uni-app x 项目。当前本地开发交付以该目录为准;上架后可通过市场的“使用 HBuilderX 导入插件”安装。
  2. 页面始终从插件根目录导入,不直接引用 utssdk 内部文件。
  3. 首次加入原生插件或更新原生代码/配置后,重新原生联编,或制作包含当前插件的自定义基座。资源包不能替换已编译的原生代码。
import * as HttpServer from '@/uni_modules/lizhao-http-server'

uni-app 使用 .vue 页面普通 JS;uni-app x 使用 .uvue 和 UTS。公开 API 名称和结果语义一致;完整示例分别维护两种语法。

接入方式选择

你的需要 从哪里开始
第一次验证服务 下方最小页面:创建 → 注册接口 → 启动 → 访问
只是提供离线网页 模块二,挂载应用可读取的目录
手机电脑互传 模块四,先配置上传,再打开协作网页
业务系统调用设备 模块三,保留自己的校验与异步业务操作
持续消息推送 模块七,普通请求与持续连接分开管理
HTTPS 或受保护服务 模块六和模块八,创建时配置安全策略

完整示例

  • uni-app:uni_modules/lizhao-http-server/example/uniapp/index.vue,使用 Options API,可供 Vue2/Vue3 项目接入。
  • uni-app x:uni_modules/lizhao-http-server/example/uniappx/index.uvue,使用 UTS 和原生 Flex 布局。
  • 协作网页:uni_modules/lizhao-http-server/example/assets/site/index.html,由示例准备到沙盒并挂载,不直接暴露源码目录。
  • 操作步骤:uni_modules/lizhao-http-server/example/readme.md。

从基础到进阶:按业务模块使用

5 分钟跑通:提供一个状态接口

uni-app:普通页面脚本

将下面页面注册到 pages.json。点击启动后,使用返回的真实 URL 访问 /api/status。页面销毁时释放自己的实例。

<template>
  <view>
    <button @click="start">启动本地服务</button>
    <text selectable>{{ address }}</text>
  </view>
</template>
<script>
import * as Http from '@/uni_modules/lizhao-http-server'
export default {
  data() { return { serverId: '', address: '等待启动' } },
  onUnload() { if (this.serverId) Http.destroyServer({ serverId: this.serverId }) },
  methods: {
    showError(error) { uni.showToast({ title: error.errMsg, icon: 'none' }) },
    start() {
      if (this.serverId) return
      Http.createHttpServer({ host: 'loopback', port: 0,
        fail: this.showError,
        success: (created) => {
          this.serverId = created.serverId
          Http.addRoute({ serverId: this.serverId, method: 'GET', path: '/api/status',
            handler: (request) => {
              Http.sendResponse({ serverId: request.serverId, requestId: request.requestId,
                bodyJson: { ok: true, time: Date.now() }, fail: this.showError })
            },
            fail: this.showError,
            success: () => Http.startServer({ serverId: this.serverId,
              fail: this.showError,
              success: (started) => {
                const info = Http.readServerInfo(started)
                if (info && info.urls.length) this.address = info.urls[0] + '/api/status'
              }
            })
          })
        }
      })
    }
  }
}
</script>

uni-app x:同一业务,用 UTS 调用

<template>
  <view>
    <button @click="start">启动本地服务</button>
    <text selectable>{{ address }}</text>
  </view>
</template>
<script setup lang="uts">
import * as Http from '@/uni_modules/lizhao-http-server'
const serverId = ref<string>('')
const address = ref<string>('等待启动')
function showError(error: Http.HttpServerFail): void {
  uni.showToast({ title: error.errMsg, icon: 'none' })
}
function start(): void {
  if (serverId.value.length > 0) return
  Http.createHttpServer({ host: 'loopback', port: 0, fail: showError,
    success: (created) => {
      serverId.value = created.serverId
      Http.addRoute({ serverId: serverId.value, method: 'GET', path: '/api/status',
        handler: (request) => {
          Http.sendResponse({ serverId: request.serverId, requestId: request.requestId,
            bodyJson: { ok: true, time: Date.now() } as UTSJSONObject, fail: showError })
        }, fail: showError,
        success: () => Http.startServer({ serverId: serverId.value, fail: showError,
          success: (started) => {
            const info = Http.readServerInfo(started)
            if (info != null && info.urls.length > 0) address.value = info.urls[0] + '/api/status'
          }
        })
      })
    }
  })
}
onUnload(() => { if (serverId.value.length > 0) Http.destroyServer({ serverId: serverId.value }) })
</script>

createHttpServer() 只创建配置,startServer() 成功才表示端口正在监听。不要在收到启动成功之前拼地址,也不要把 0.0.0.0 当成浏览器访问地址。

各段示例假设已经取得 serverId,并有上面的 showError()。可放入自己的按钮事件或业务方法。普通操作只需添加所需配置。

模块一:局域网与多服务管理

将创建配置中的 host 改为 lan,启动后把 info.urls 中的实际 LAN 地址交给同网设备。地址存在不等于所有网络都允许设备互通;访客 Wi-Fi、热点隔离、权限或防火墙可能影响访问。

Http.stopServer({ serverId: serverId.value, fail: showError })
// 停止后保留路由和配置,可再次启动。
Http.restartServer({ serverId: serverId.value, fail: showError })
// 另一个业务使用另一个实例,不与当前服务共享请求或连接。
Http.createHttpServer({ serverId: 'media-service', host: 'loopback', port: 0, fail: showError })

destroyServer() 永久释放该实例;重新创建同名实例会产生新的请求代次,旧请求不能响应到新实例。

模块二:离线网页、静态目录与 SPA

先把网页放入应用实际可读取的目录,再挂载。完整示例通过 uni.getFileSystemManager() 在自己的沙盒创建网页和清单,不申请全盘存储权限。

Http.mountStatic({ serverId: serverId.value, path: '/site',
  rootPath: uni.env.USER_DATA_PATH + '/my-site', index: 'index.html',
  cacheControl: 'no-cache', allowDirectoryListing: false,
  fail: showError
})

如果是前端路由应用,可增加 spaFallback: 'index.html'。缺失的 JS/CSS 等资源不会被错误替换为 HTML。目录浏览默认关闭;挂载目录外的文件不会作为静态资源暴露。

打包资源与真实文件系统路径可能不同,尤其 Android 的压缩 assets;参见本文“注意事项”中的平台与资源说明,不要直接把插件源码路径当成安装后的文件路径。

模块三:把 HTTP 请求接到真实业务

路径参数、查询、头、表单统一用 name/value 数组,保留重复字段。使用 getField() / getHeader() 读取单个值。

Http.addRoute({ serverId: serverId.value, method: 'GET', path: '/devices/:id',
  handler: (request) => {
    const id = Http.getField(request.params, 'id')
    Http.sendResponse({ serverId: request.serverId, requestId: request.requestId,
      bodyJson: { deviceId: id, state: 'waiting' } as UTSJSONObject, fail: showError })
  }, fail: showError
})

异步查询也使用原来的 requestId 响应。每个请求只能结束一次,超过等待时间、断开、取消或实例销毁后会返回明确错误。JSON 正文在 bodyText 中保持完整,数组、标量和 null 不会被冒充对象;二进制通过受控临时文件返回。

模块四:普通上传与分片续传

Http.configureUpload({ serverId: serverId.value, path: '/transfer',
  directory: uni.env.USER_DATA_PATH + '/received-files',
  resumable: true, maxFileBytes: 134217728, maxTotalBytes: 268435456,
  fail: showError
})

普通上传使用 POST /transfer 和 multipart 表单,返回 files 与 form;文件记录包含原字段名、原文件名、实际唯一保存路径、类型和大小。插件不会按客户上传的文件名覆盖原文件。

分片会话包含创建、状态查询、提交分片、完成与取消。完整协议和独立浏览器请求示例见下方“分片上传协议”。同一会话支持相同内容重试;不允许不同内容覆盖已接收字节。它是本插件的协议,不能直接当作任意上传 SDK 的服务端实现。

分片上传协议

先调用 configureUpload,配置 path: '/transfer'、可写 directory、resumable: true。下面 URL 都相对同一真实服务地址;鉴权配置同普通请求。

顺序与响应
步骤 请求 输入 成功响应
创建 POST /transfer/sessions JSON {fileName,totalBytes,sha256?} uploadId 与状态
查询 GET /transfer/sessions/:uploadId 无正文 offset、totalBytes 与状态
追加 PATCH /transfer/sessions/:uploadId Upload-Offset 头、二进制正文 新 offset
完成 POST /transfer/sessions/:uploadId/complete 无正文 完成文件记录
取消 DELETE /transfer/sessions/:uploadId 无正文 取消状态
参数 类型 必填 说明 默认值 可选参数
fileName string 是 用户文件名,仅元数据,不作为任意路径 无 安全文件名
totalBytes number 是 文件总字节 无 0 或不超上限的整数
sha256 string 否 整文件 SHA-256 不额外校验摘要 64 位十六进制
Upload-Offset HTTP header PATCH必填 本分片开始字节 无 与服务器偏移一致

接收采用连续偏移,成功后再提交下一段。相同偏移、相同字节的重试可幂等接受;不同内容覆盖或乱序提交返回 409,客户端应先查询状态。大于请求体、文件或会话容量的请求返回 413,不能通过分片绕过总量限制。

完成前校验总长度和已提供的 SHA-256,再把本插件临时产物转为最终唯一文件;旧文件不会被覆盖。失败保留真实原因,取消/过期清理属于该会话的未完成文件。completed/cancelled 状态如何保留、停服后会话是否保留取决于平台当前实现,见平台说明;本插件不声称跨重装永久续传。

浏览器真实调用
// base 为 startServer 成功后取得的 URL,file 是用户选择的 File。
async function transfer(base, file, headers = {}) {
  async function request(path, options = {}) {
    const response = await fetch(base + path, { ...options,
      headers: { ...headers, ...options.headers } })
    const text = await response.text()
    if (!response.ok) throw new Error('HTTP ' + response.status + ' ' + text)
    return text ? JSON.parse(text) : {}
  }
  const created = await request('/transfer/sessions', { method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ fileName: file.name, totalBytes: file.size }) })
  const path = '/transfer/sessions/' + encodeURIComponent(created.uploadId)
  let offset = (await request(path)).offset
  while (offset < file.size) {
    const chunk = file.slice(offset, Math.min(offset + 1048576, file.size))
    await request(path, { method: 'PATCH',
      headers: { 'Upload-Offset': String(offset), 'Content-Type': 'application/octet-stream' },
      body: chunk })
    offset += chunk.size
  }
  return request(path + '/complete', { method: 'POST' })
}

生产业务应持久化自己的 uploadId 与文件身份,恢复前查询服务器偏移并确认同一文件。协作示例将会话保留在页面内存,适合一次联调;完整刷新页面后不会冒充已恢复。

普通 multipart POST /transfer 返回 files/form。字段重复用数组保留;文件保存路径为应用端结果,不是电脑可直接打开的路径。客户端选择文件内容属于业务传输,日志报告只记录大小、字段结构和阶段摘要。

模块五:文件下载与本地媒体

Http.addRoute({ serverId: serverId.value, method: 'GET', path: '/media/video',
  handler: (request) => {
    Http.sendResponse({ serverId: request.serverId, requestId: request.requestId,
      filePath: uni.env.USER_DATA_PATH + '/videos/demo.mp4',
      contentType: 'video/mp4', fail: showError })
  }, fail: showError
})

文件存在并可读取时才发送真实内容。HEAD 无正文,单区间 Range 返回 206,越界返回 416;多区间请求回退完整 200。可通过静态目录提供 .m3u8 与分片文件,保持播放列表相对路径正确。播放器格式支持与 HTTP 响应分别排查。

模块六:访问控制与跨域

创建时配置 security: { token: '由业务生成的临时令牌' }。客户端用 Authorization: Bearer … 或 X-Http-Token 发送;令牌不放入 URL。Basic 使用系统标准 Authorization;同时配置 Token 和 Basic 时,两项均须满足,可组合 X-Http-Token 与 Basic Authorization。

Http.createHttpServer({ host: 'lan', port: 0,
  security: { token: '由业务生成的临时令牌', requestsPerMinute: 120 },
  cors: { allowedOrigins: ['https://your-business.example'],
    allowedMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],
    allowedHeaders: ['Content-Type', 'X-Http-Token', 'Upload-Offset'] },
  fail: showError
})

CORS 只是浏览器来源规则,不替代鉴权。浏览器 WebSocket、video 标签和下载导航不能随意添加自定义请求头;使用受保护实时/媒体服务时,要选择能满足认证协议的客户端。完整示例提示这类限制,不把握手失败显示为成功。

模块七:SSE 与 WebSocket

Http.addSseRoute({ serverId: serverId.value, path: '/events', heartbeatMs: 15000, fail: showError })
Http.addWebSocketRoute({ serverId: serverId.value, path: '/ws', maxMessageBytes: 1048576, fail: showError })
Http.sendSseEvent({ serverId: serverId.value, event: 'device', data: '{"state":"ready"}', fail: showError })
Http.sendWebSocketMessage({ serverId: serverId.value, text: '设备已就绪', fail: showError })

未指定 connectionId 时只广播到本实例;结果中的 accepted 为已交给发送链的连接数,不表示对端业务已经消费。用 onServerEvent() 监听连接、消息与关闭,用 offServerEvent(listenerId) 释放监听。SSE 是否重放 Last-Event-ID 由业务负责。

模块八:HTTPS 与固定上游代理

Android/iOS 的 TLS 身份由业务提供 PKCS12 文件,Harmony 使用 PEM 证书与私钥文件。文件必须在应用授权可读的位置,口令不写日志;客户端仍须信任证书。

Http.createHttpServer({ host: 'loopback', port: 0,
  tls: { identityPath: uni.env.USER_DATA_PATH + '/server-identity.p12', password: '运行时输入的口令' },
  success: (created) => {
    serverId.value = created.serverId
    Http.addProxy({ serverId: created.serverId, path: '/upstream',
      target: 'https://your-business.example/api', timeoutMs: 15000,
      success: () => Http.startServer({ serverId: created.serverId,
        success: (started) => {
          const info = Http.readServerInfo(started)
          if (info != null && info.urls.length > 0) address.value = info.urls[0] + '/upstream'
        }, fail: showError }), fail: showError })
  },
  fail: showError
})

该例创建新实例,运行前先销毁基础示例的旧实例,再填入自己可访问的身份文件与上游地址。Harmony 把 tls 换为 certificatePath / privateKeyPath 的 PEM 配置,其余创建、注册、启动顺序一致。

代理目标由应用注册,客户端不能传任意上游地址。默认不跟随上游重定向,也不向上游透传本地访问凭据或 Cookie;应用通过 proxy.headers 显式设置自己的上游认证。系统 TLS 校验保持启用。创建本地服务不会自动开放公网或做内网穿透。

模块九:排查问题与释放资源

在完整示例复现后点击底部“一键复制日志”。报告包含插件/示例构建来源、运行环境、原生快照和保留的完整操作轨迹;长日志按同一快照分段复制,复制失败不会跳过分段。

const listenerId = Http.onServerEvent((event) => {
  // 仅记录足够排查的脱敏摘要,消息/请求正文由自己的业务处理。
  console.log(event.type, event.serverId, event.requestId)
})
Http.getDiagnostics({ serverId: serverId.value,
  success: (result) => { console.log(JSON.stringify(result.data)) }, fail: showError })
// 页面销毁或业务结束。
Http.offServerEvent(listenerId)
Http.destroyServer({ serverId: serverId.value, fail: showError })

HX、编译器和资源构建标记来自构建期注入;运行时版本单独读取;不可获取的信息明确显示 unknown。页面构建摘要不证明原生基座匹配,原生标记要与对应编译产物核对。

API 用途速查

API 参数类型 用途
createHttpServer CreateHttpServerOptions 创建配置与实例,不监听
startServer / stopServer / restartServer / destroyServer HttpTargetOptions 监听、停止保留配置、换代重启、永久释放
getServerInfo / listServers HttpTargetOptions / HttpQueryOptions 当前实例 / 实例列表
getServerCapabilities / getNetworkAddresses HttpQueryOptions 原生能力与限制 / 实际网卡地址
addRoute / removeRoute / listRoutes HttpRouteOptions / HttpRemoveRouteOptions / HttpTargetOptions 注册、移除和查询动态路由
sendResponse / cancelRequest HttpResponseOptions / HttpCancelRequestOptions 终结 HTTP 请求
mountStatic / unmountStatic HttpStaticOptions / HttpUnmountOptions 静态目录挂载与移除
configureUpload / listUploads / cancelUpload HttpUploadOptions / HttpTargetOptions / HttpCancelUploadOptions 上传路径和会话管理
addProxy / removeProxy HttpProxyOptions / HttpRemoveProxyOptions 固定上游代理注册与释放
addSseRoute / addWebSocketRoute HttpStreamRouteOptions 注册持续连接端点
sendSseEvent / closeSse HttpSseSendOptions / HttpCloseStreamOptions SSE 单播/广播、关闭
sendWebSocketMessage / closeWebSocket HttpWebSocketSendOptions / HttpCloseStreamOptions WS 文本/二进制与关闭
prepareStaticAssets HttpPrepareAssetsOptions 准备真实可读的资源目录
getDiagnostics / clearDiagnostics HttpQueryOptions 读取/清空诊断缓存,不改变业务资源
onServerEvent / offServerEvent HttpServerEventListener / listenerId 订阅并返回独立标识 / 释放监听
readServerInfo HttpResult 生命周期结果转为 HttpServerInfo 或 null
getHeader / getField 头/字段数组、名称 读取第一个命中字段;头忽略大小写

核心配置

参数 类型 必填 说明 默认值 可选参数
host string 否 监听模式 loopback loopback / lan / address
address string 否 address 模式的明确 IP 127.0.0.1 实际可绑定的 IP
port number 否 0 由系统分配,否则指定端口 0 0 / 1024..65535
serverId string 否 自定义实例编号,不能重复占用 自动生成 非空编号
maxConnections number 否 并发连接上限 16 正整数
maxBodyBytes number 否 单次请求体上限,单位字节 67108864 正整数
requestTimeoutMs number 否 业务响应等待时间 30000 正整数,毫秒
cors HttpCorsOptions 否 来源与预检规则 关闭 见本节 CORS 参数
security HttpSecurityOptions 否 鉴权和访问限制 关闭 见模块六
tls HttpTlsOptions 否 证书身份,配置后使用 HTTPS 关闭 见模块八
diagnosticsEnabled boolean 否 详细原生诊断 false true / false

头部、读写、空闲、上传与发送队列限制见本节后续参数表。单次上传同时受请求体和上传配置限制;较大文件建议使用分片会话。

所有 API 从 @/uni_modules/lizhao-http-server 根目录导入。除三个读取 helper 与事件订阅/释放外,操作采用 options 对象和 success/fail/complete,均不返回 Promise。

success 或 fail 至多一次,随后 complete 一次。success 的 HttpResult.data 是完整 UTSJSONObject;uni-app JS 可读普通属性,UTS 用 getString/getNumber/getJSON 或 readServerInfo()。complete 给 errSubject/errCode/errMsg/operation/serverId;成功 errCode 为 0。HTTP 状态码与插件 errCode 是两类信息。

公共回调与标识

参数 类型 必填 说明 默认值 可选参数
serverId string 实例操作必填 当前实例编号;创建时可省略 创建时自动生成 不重复的编号
success HttpSuccessCallback 否 成功对象含 operation/serverId/data 无 回调
fail HttpFailCallback 否 固定主题、错误码及原生原因 无 回调
complete HttpCompleteCallback 否 成功/失败后结束通知 无 回调

查询全部实例/能力/地址时 serverId 可省略。同步监听 onServerEvent(listener) 返回 listenerId,必须用 offServerEvent(listenerId) 释放。事件回调不是一次性 success,页面销毁还应销毁自己创建的实例。

创建与服务结果

创建配置除上方“核心配置”表外还有:

参数 类型 必填 说明 默认值 可选参数
maxPendingRequests number 否 等待业务响应数量上限 64 正整数
maxHeaderBytes number 否 请求头总字节上限 32768 正整数
headerTimeoutMs number 否 读取完整头的期限 10000 正整数
bodyTimeoutMs number 否 请求体读取期限 60000 正整数
idleTimeoutMs number 否 Keep-Alive 空闲期限 15000 正整数
maxSendQueueBytes number 否 连接发送队列上限 4194304 正整数

0 不隐式表示无限。port 0 的成功结果中 port 为实际端口。HttpServerInfo 含 serverId/state/host/address/port/scheme/urls/generation/activeConnections/pendingRequests/requestCount/receivedBytes/sentBytes/nativeBuildMarker。

状态依次为 created、starting、running、stopping、stopped;destroyed 不可重新启动。重启保留配置并生成新的 generation;停止或销毁终结待响应请求、连接和传输。

路由、请求与响应

参数 类型 必填 说明 默认值 可选参数
method HttpMethod 是 路由方法 无 GET/POST/PUT/PATCH/DELETE/OPTIONS/HEAD/ALL
path string 是 路径与参数,如 /devices/:id 无 绝对 URL 路径
routeId string 否 路由标识;替换时用新标识保留在途处理器 自动生成 非空编号
replace boolean 否 显式替换相同方法/路径 false true/false
handler HttpRouteHandler 是 收到完整请求元数据后处理业务 无 可异步响应

可匹配的路由按精确路径、参数路径、尾部前缀依次选择。例如同时注册 /devices/status、/devices/:id 和 /devices/* 时,访问 /devices/status 进入精确路由,访问 /devices/123 进入参数路由;路径长度不会使前缀路由越级。方法不匹配时继续寻找可处理该方法的候选,无可用方法返回 405。

HttpRequest 字段:serverId/requestId/routeId/method/rawPath/path/query/params/headers/form/files/bodyKind/bodyText/bodyFilePath/bodySize/remoteAddress/protocol。name/value 数组保留重复 query/form;JSON 的完整文本保留在 bodyText,业务可解析为自己的类型。

正文桥接有独立安全上限:较大文本/JSON 请求可能收到 413;二进制和文件采用落盘路径。具体平台上限由能力/平台说明列出。不要把 binary 当 UTF-8 强行读取。

参数 类型 必填 说明 默认值 可选参数
requestId string 是 来自 handler 的本次请求标识 无 活跃请求
statusCode number 否 HTTP 响应状态 200 200..599;1xx 由原生协议管理
headers HttpHeader[] 否 自定义头,name/value 无 不含 CR/LF
contentType string 否 响应 MIME 按正文/文件推断 有效 MIME
bodyText string 否 文本正文 无 与其他主体互斥
bodyJson UTSJSONObject 否 JSON 对象 无 与其他主体互斥
bodyJSONText string 否 完整 JSON,含数组/标量/null 无 必须合法 JSON
bodyBase64 string 否 有界二进制正文 无 合法 Base64
filePath string 否 原生可读取的文件 无 与其他主体互斥
downloadName string 否 下载附件名 无 头注入字符拒绝

主体字段至多填写一个;全部省略表示空正文。HEAD/204/304 不发送正文。文件流负责 Range、If-Range、ETag 和 Last-Modified;多区间 Range 返回完整 200。文件响应接受仅表示已交给发送链,真正发送结果从 requestFinished/错误事件读取。

静态挂载

参数 类型 必填 说明 默认值 可选参数
mountId string 否 挂载标识,用于移除 自动生成 唯一编号
path string 是 URL 前缀,如 /site 无 绝对路径
rootPath string 是 存在且可读的根目录 无 原生文件路径
index string 否 默认首页 index.html 根目录内文件
spaFallback string 否 仅业务路由缺失时回退 关闭 根目录内 HTML
allowDirectoryListing boolean 否 无首页时列目录 false true/false
cacheControl string 否 缓存策略 未额外指定 合法头值
mimeTypes HttpHeader[] 否 name 为扩展名,value 为 MIME 内置映射 自定义覆盖

规范化路径和真实路径须在挂载根内部;编码点段、分隔符、NUL 和软链接逃逸拒绝访问。目录浏览不会自动开放上级目录。

上传

参数 类型 必填 说明 默认值 可选参数
path string 是 上传前缀 无 绝对路径
directory string 是 受控保存目录 无 应用可写目录
maxFileBytes number 否 单文件上限,字节 134217728 正整数
maxFiles number 否 普通请求文件数 8 正整数
maxTotalBytes number 否 上传会话容量上限,字节 268435456 正整数
resumable boolean 否 开放本插件续传协议 false true/false
sessionTTLSeconds number 否 未完成会话有效期 3600 正整数

普通请求总正文仍受 maxBodyBytes 约束。上传文件使用唯一保存名,files 中保留原 fileName;完成的文件交给应用使用,取消/错误只清理属于插件且未接收的临时产物。已完成/取消会话、过期策略与响应见 本文模块四“分片上传协议”。

CORS、鉴权、TLS 与代理

参数 类型 必填 说明 默认值 可选参数
cors.allowedOrigins string[] 配置CORS时必填 来源白名单 CORS关闭 明确来源或 *
cors.allowedMethods string[] 否 允许的方法 常用方法 按业务枚举
cors.allowedHeaders string[] 否 允许的自定义头 按平台默认 建议显式列出
cors.exposedHeaders string[] 否 前端可读取的响应头 无 如 Content-Range
cors.allowCredentials boolean 否 跨域凭证 false 开启时不用通配来源
cors.maxAgeSeconds number 否 预检缓存 按默认 非负秒数
security.token string 否 Bearer 或 X-Http-Token 关闭 运行时传入
security.basicUser/basicPassword string 否 Basic 用户/口令 关闭 配套填写,建议 TLS
security.allowedIPs string[] 否 远端 IP 白名单 无限制 实际 IP
security.allowedHosts string[] 否 Host 白名单 无限制 实际 Host
security.requestsPerMinute number 否 每客户端窗口请求限制 关闭 正整数
tls.identityPath/password string Android/iOS TLS PKCS12 身份及口令 关闭 应用可读身份
tls.certificatePath/privateKeyPath string Harmony TLS PEM 证书与私钥 关闭 应用可读文件
proxy.path string 是 本地代理前缀 无 绝对路径
proxy.target string 是 固定上游 无 HTTP/HTTPS
proxy.headers HttpHeader[] 否 应用配置的上游头 无 合法值
proxy.timeoutMs number 否 上游超时 按默认 正整数

认证覆盖静态/上传/代理和握手。CORS 预检按配置处理,不把 CORS 当作身份认证。代理移除逐跳头及下游 Authorization/Cookie/X-Http-Token,不自动跟随重定向;应用通过 proxy.headers 显式配置上游凭据,不使用会形成循环的自身地址。

实时流与事件

参数 类型 必填 说明 默认值 可选参数
stream.path string 是 SSE/WS 端点 无 绝对路径
stream.heartbeatMs number 否 心跳间隔 15000 正整数
stream.maxMessageBytes number 否 WS 单消息上限 1048576 正整数
stream.subprotocols string[] 否 WS 子协议列表 无 合法协议名
connectionId string 关闭必填/发送可省略 单连接或本实例广播 广播 当前活跃连接
SSE data/event/id/retryMs string/string/string/number data必填 合法 SSE 字段 其余省略 换行按协议编码
WS text/base64 string 二选一 文本或二进制消息 无 不可同时填写
close code/reason number/string 否 WS 关闭代码与原因 正常关闭 合法代码与 UTF-8 长度

事件含 type/serverId/requestId/connectionId/time/level/message/dataJSON。常见 type:started、stopped、error、requestFinished、uploadProgress、uploadCompleted、uploadCancelled、sseOpen、sseClose、webSocketOpen、webSocketMessage、webSocketClose。WS message 的 dataJSON 给 text 或 base64;正文属于业务数据,不应自动写入诊断日志。

错误码说明

errSubject 固定为 lizhao-http-server。插件错误码与 HTTP 响应状态码分别处理;失败时保留 errCode、errMsg、操作和请求关联信息。

错误码 含义 排查方向
9301001 平台/能力不支持 能力快照和平台矩阵
9301002 参数无效 字段类型、范围、JSON、互斥主体
9301003 服务或资源不存在 serverId/文件/路由标识
9301004 状态冲突 重复实例、运行状态、路由冲突
9301005 监听绑定失败 地址、端口、权限、原生原因
9301006 文件/网络读写失败 路径、访问权、磁盘、连接
9301007 请求过期或断开 请求时间、代次与连接事件
9301008 已完成响应 重复业务回调或重复 sendResponse
9301009 资源上限 连接、大小、队列、会话容量
9301010 超时 读取、业务或上游阶段
9301011 权限/鉴权拒绝 LAN 权限、Token/Basic/IP/Host
9301012 TLS 失败 身份文件、口令、证书链、握手
9301013 上游代理失败 目标、状态、网络、证书
9301014 操作取消 取消来源与已释放状态
9301015 原生内部错误 完整原生类型/堆栈/原因与报告

errSubject 固定 lizhao-http-server。fail 保留 operation/serverId/requestId/nativeType/nativeStack/nativeCause;报告层对敏感路径和认证数据脱敏。不可获取的堆栈为空并在诊断中说明来源,不伪造。

注意事项

支持范围、权限与基座

目标 App 平台为 Android、iOS、HarmonyOS;公开接口用于 uni-app 与 uni-app x。Web 和小程序返回不支持监听的错误。对应原生实现、编译与设备验收状态在平台说明中分别列出,不能用资源生成替代原生包或真机结果。

Android 使用网络权限;iOS 局域网访问需要用途说明及用户授权;Harmony 使用 INTERNET 与用于枚举实际网卡地址的 GET_NETWORK_INFO。新原生代码与配置必须进入匹配的基座或正式包。App 后台行为由系统决定,尤其 iOS,不承诺长时间后台永久监听。

  • 局域网服务需要同网可达;使用真实返回地址,不把监听地址 0.0.0.0 当作访问地址。
  • Token、Basic、证书口令与上游认证由业务管理;CORS 不代替鉴权。
  • 页面退出后释放自己的监听、持续连接和服务;停止、销毁和清空诊断具有不同含义。

平台范围

平台 原生路线 宿主 当前验证层级
Android Kotlin / 系统 Socket、文件、TLS uni-app / uni-app x 核心独立客户端网络回归、两种真实宿主 SDK 类型/链接与公开签名;匹配基座/设备未验
iOS Swift / Network、Foundation、Security uni-app / uni-app x 两宿主资源生成及 Swift 语法解析;Windows 缺少 Apple SDK,Xcode 类型/链接和设备未验
HarmonyOS ArkTS / NetworkKit、文件、自有 NAPI 原子发布 uni-app(Vue3)/ uni-app x 9 原生模块真实 SDK、28 项纯协议、两个宿主真实 HAR 联编;原子辅助三 ABI 编译及同生产内核竞争检查;HAP/设备未验
Web / 小程序 无应用 TCP 监听权限 两宿主 监听等 API 返回 9301001,不产生假服务

本地实现候选与市场已发布状态不同。package 中 Android 的支持来自两宿主真实 SDK 验证,Harmony 的支持来自两宿主真实 HAR 联编;iOS 因缺少 Apple SDK 保留待验证声明。内部最终结果记录各检查实际覆盖的源码摘要,不从源码存在或资源导出成功推断真机业务通过。

系统与工具范围

  • Android 原生代码按 API21 起编写;本次真实类型检查使用 Android36 SDK。API21..25 的文件发布分支尚未在设备执行。
  • iOS 配置最低系统12,arm64;本次没有 Apple SDK 联编,不承诺未实际编译的系统组合。
  • Harmony 的 uni-app 宿主仅支持Vue3,Options API示例可复用;Vue2不支持Harmony。
  • Harmony 插件完整原生 API 使用 API12 起接口;本次真实 SDK 为6.0.0.47/API20。当前 HBuilderX 自带 Vapor 运行库要求兼容 API20,普通 uni-app 运行库要求 API12。宿主要求可高于插件所用 API。
  • package 的工具最低范围与本次实际 HBuilderX 编译环境对应。示例报告通过构建前脚本注入实际 HX/编译器版本;运行时版本另行读取,未知字段保留 unknown。

权限与网络

Android 的 INTERNET、ACCESS_NETWORK_STATE 为普通权限。当前插件不额外申请 LAN 运行时权限;若宿主的系统/target SDK 组合启用了额外局域网限制,应用须按该系统要求处理授权。宿主访问 HTTP 的明文策略需要按业务配置;服务监听成功不证明 web-view 或播放器已允许明文访问。

iOS 使用局域网时,宿主 Info.plist 必须有 NSLocalNetworkUsageDescription,应用处理授权拒绝/撤回。网络 API 未提供可查询状态时显示 unknown;不能从回环请求成功推断 LAN 已授权。

Harmony 在官方 module.json5 声明 ohos.permission.INTERNET 和 GET_NETWORK_INFO;后者用于枚举真实网络地址,属于直接相关的普通权限。TCP/TLS 端口0成功后的端口来自实际 Socket,不使用配置中的0作为访问端口。

返回地址来自实际网卡和绑定端口。LAN 全网卡监听地址不是访问网址;同网络、网络隔离、权限和防火墙均影响可达性。代理上游与 LAN 入站访问是两条独立链路。

访问策略差异

Android/Harmony 的 IP 规则支持精确地址与 CIDR;iOS 当前仅精确 IP。Android/iOS Host 规则可匹配完整 authority 或去端口后的主机;Harmony 当前精确匹配含端口的 Host authority,配置 localhost:3000 与 localhost 不等价。

同时配置 Token 与 Basic 时两种规则都须满足,可使用 X-Http-Token 配合 Basic Authorization。合法 CORS 预检跳过 Token/Basic,仍检查 Origin、IP、Host、限速;实际业务请求执行全部认证。带 credentials 的 CORS 来源不能用通配符。

固定代理默认不把本地访问凭据及 Cookie 转交上游。需要上游认证时,应用通过 proxy.headers 显式配置自己的凭据;不自动跟随重定向,不默认关闭系统证书校验。

文件与打包资源

静态根目录/上传目录须真实存在或可创建,并属于应用有权访问的目录。Android content URI、APK assets、iOS Bundle、Harmony rawfile 与普通绝对文件路径不同;prepareStaticAssets 只能在该端可访问时返回真实准备后的目录,失败必须处理。

示例通过宿主 FileSystemManager 创建自己的沙盒目录,不能传开发电脑路径或 uni_modules 源码路径。Android 压缩 assets 不可直接当普通文件目录;打包站点应先按平台资源 API 复制到沙盒。Harmony 接受可访问的实体绝对路径/file://,不把未导出的 rawfile 或虚拟 URI当文件系统路径。

大文件在原生分块读写;动态文本/JSON 的跨桥上限为4MiB,过大时返回413,不静默截断。Android 在上传暂存发布中使用系统原子操作,旧系统/文件系统不支持时返回真实错误。Harmony 续传完成的发布使用自有内核非覆盖操作,跨卷或系统不支持时不降级覆盖;实际依赖及 ABI 见最终构建证据。

二进制请求临时路径通常只在该请求响应完成前有效;业务要永久留存须复制到自己管理的目录。完成的上传文件由应用管理,停止服务不会删除已交付文件。媒体 HTTP 可读取不保证播放器支持对应编码。

传输、TLS与持续连接

Android/iOS HTTPS 身份为 PKCS12;Harmony为 PEM 证书与私钥。需要完整证书链和客户端信任,不能用一种平台的身份参数替代另一平台。

Android/Harmony 固定代理在原生分块传输。iOS 客户端正文先保存到临时文件再由 URLSession 文件任务上传,响应逐块发送;内存有界,但不承诺收包和转发同时进行。Harmony multipart 同样先落有界暂存文件再按块解析。

续传会话属于当前应用与实例;停服、销毁、进程退出或系统清理可能终止未完成会话。恢复前查询 uploadId 的真实状态,不能承诺跨重装或永久历史恢复。

SSE/WebSocket 有界发送队列。accepted 仅指入队/接受,消息是否被对端业务消费需自己的确认协议。当前不提供 WS 压缩扩展、HTTP/2 或客户端证书认证。多区间 Range 返回完整200。

后台、诊断与基座

系统可以暂停或回收后台 App,iOS 尤其不能承诺长期后台永久监听。业务结束时 offServerEvent、停止/销毁自己创建的实例,不为保活申请无关后台能力。

nativeBuildMarker 是实现标识,不能代替实际安装包哈希或基座身份。页面 sourceSHA256 记录本次构建源码,不能据此证明客户安装的原生库已更新。必须同时核对应用包、原生基座与资源构建信息。

新增插件或原生源码、依赖、权限、配置、资源变化后需要重新原生联编,或制作匹配基座/正式包。appResource/wgt 不能更新已编译的原生部分。普通文档和样式变更通常不需重打原生基座。

验收分别区分静态语法、语言转换/项目资源编译、SDK原生类型/链接、HAR/HAP或Apple联编、匹配基座、真机业务和系统剪贴板。桌面报告测试不替代实际剪贴板内容验收。最新具体结果和未验范围以开发交付记录为准。

常见问题

现象 先检查什么 处理
创建成功但打不开 是否收到 startServer.success 创建只保留配置,启动成功后才访问真实返回地址
本机可访问,电脑失败 LAN模式、实际地址、网络隔离、权限 用同网设备;核对 iOS/LAN 权限和真实网络,不拿回环地址给电脑
端口绑定失败 地址属于当前设备吗、端口是否占用 先试 port:0;保留 9301005 原生原因
web-view/播放器失败 客户端明文策略、证书信任、编码支持 分别验证 HTTP 响应和媒体格式,不以监听结果代替播放
上传收到413 maxBodyBytes/maxFileBytes/maxTotalBytes 根据业务调整对应范围,或使用分片会话
分片收到409 查询 offset、确认同一文件与内容 从服务器实际偏移继续,不能覆盖不同字节
重复响应9301008 业务回调是否重复、超时与完成竞态 每 requestId 只发送一个终结结果
请求9301007 连接断开、超时、重启代次、销毁 不用旧 requestId 重试新实例请求
鉴权401/403 Token/Basic/IP/Host配置 检查字段与客户端头;CORS不替代认证
浏览器WS/媒体带令牌失败 客户端能否发送认证头 浏览器API能力有限,选择匹配客户端;不把令牌写网址
HTTPS失败 身份文件可读、口令、证书链、客户端信任 保留 TLS 错误;不默认关闭证书校验
原生标记与页面不匹配 基座/包与资源的构建身份 重新联编或安装匹配基座,页面热更不能更新原生
复制日志失败 剪贴板实际 fail、报告长度 使用固定快照分段;失败不推进;长按完整报告手动复制

复现后在完整示例底部点击“一键复制日志”,保留报告编号与所有段。提供实际安装包/基座类型、复现步骤、错误前后状态和完整报告即可;避免发送客户文件正文、密码或认证头。

报告中的 unknown 表示该平台无法采集或未注入,不是被推测出的版本/权限。完整原生异常与来源用于判断是参数、网络、文件、宿主桥或平台问题;静态检查不能确认客户包已经修复。

作者系列 UTS 插件

以下为作者已在 DCloud 插件市场上架的 UTS 插件,可按业务场景组合使用。最新发布内容可查看作者主页。

插件 能力方向 插件市场
lizhao-app-keepalive 应用保活、唤醒、自愈与报告 查看插件
lizhao-bg-audio 背景音频播放、队列、倍速与事件 查看插件
lizhao-ble BLE 扫描、连接、读写、通知与自动重连 查看插件
lizhao-call-kit 电话、短信、通讯录原生能力 查看插件
lizhao-camera-pro 原生相机、拍照录像、水印与媒体保存 查看插件
lizhao-cast-screen DLNA 投屏、AirPlay 路由入口 查看插件
lizhao-choose-file 原生文件选择、上传、进度与取消 查看插件
lizhao-device-id 设备标识、隐私策略与诊断 查看插件
lizhao-doc-corrector 文档扫描、矫正、增强与识别 查看插件
lizhao-emu-detect 模拟器环境检测、风险评分与证据 查看插件
lizhao-float-window 悬浮窗、画中画、权限与诊断 查看插件
lizhao-gallery-pro 相册媒体分页、筛选、缩略图与导出 查看插件
lizhao-hce-card NFC 虚拟卡、APDU 交互与 NDEF 标签模拟 查看插件
lizhao-health 健康数据授权、查询、统计与写入 查看插件
lizhao-icon-pro SVG 图标组件、多主题与缓存 查看插件
lizhao-nfc-pro NFC 标签读写、NDEF、IsoDep 与诊断 查看插件
lizhao-notify-pro 本地通知、点击动作、进度与定时提醒 查看插件
lizhao-novel-reader 原生小说阅读、仿真翻页与段落评论 查看插件
lizhao-pdf-pro PDF 阅读、签批、真实写回与页面处理 查看插件
lizhao-scan-pro 原生扫码、连续扫码、相册识别 查看插件
lizhao-serial-port 路径串口、USB 串口、多会话收发与诊断 查看插件
lizhao-share-plus 系统分享、远程文件下载后分享 查看插件
lizhao-smart-tts 系统 TTS、云端合成、听书方案 查看插件
lizhao-sqlite-pro 原生 SQLite、迁移、备份与诊断 查看插件
lizhao-sse-pro SSE、Line、JSONL 与 Raw 流式请求 查看插件
lizhao-tcp-pro TCP 客户端、服务端、多连接与诊断 查看插件
lizhao-usb-storage U 盘、移动硬盘文件浏览、读写与批量复制 查看插件
lizhao-video-editor 视频裁剪、压缩、取帧与 FFmpeg/FFprobe 查看插件
lizhao-video-feed 短视频上下滑、短剧选集与分页加载 查看插件
lizhao-video-thumb 视频封面、批量取帧与 Base64 返回 查看插件
lizhao-vpn-pro 企业 VPN、IKEv2、安全接入与脱敏诊断 查看插件
lizhao-wechat-kit 微信登录、分享、支付、小程序与客服 查看插件

隐私、权限声明

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

Android INTERNET/ACCESS_NETWORK_STATE;iOS局域网用途说明;Harmony INTERNET/GET_NETWORK_INFO。存储仅使用应用沙盒或应用授权目录。

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

按应用主动配置在本机或局域网处理请求;插件不默认上传诊断或客户数据

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

无

暂无用户评论。