更新记录

1.1.0(2026-08-11) 下载此版本

1.修复 uni-app 项目兼容问题

1.0.1(2026-07-24) 下载此版本

1.修复 iOS 端 HttpRoute 接口的连续回调问题

1.0.0(2026-07-23) 下载此版本

初始版本

查看更多

平台兼容性

uni-app(4.31)

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 13 1.0.0 12 1.0.0
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(4.31)

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

其他

多语言 暗黑模式 宽屏模式
×

xyz-httpserver

嵌入式 HTTP 服务器插件,Express 风格 API,支持 Android、iOS、HarmonyOS 三端。

同时兼容 uni-app x.uvue / .uts)和 uni-app.vue / .ts)两种项目环境。

功能特性

  • Express 风格路由注册(get/post/put/delete/patch/all)
  • 链式响应 API(status/setHeader/contentType/send/json)
  • 同一路径多方法绑定(route)
  • 内置 CORS 中间件
  • 静态文件服务
  • 服务器生命周期事件(onStart/onStop/onRequest/onError)
  • 响应支持文本、JSON、二进制(ArrayBuffer)三种格式

环境差异注意事项

功能 uni-app x uni-app
req.formParams 遍历 UTSJSONObject.keys(obj) Object.keys(obj)
send(ArrayBuffer) ✅ 直接发送二进制 ❌ 不支持,需转 base64 字符串发送

安装

将插件导入项目 uni_modules 目录即可使用。

基本用法

import { createHttpServer, HttpServerTask, HttpRequest } from "@/uni_modules/xyz-httpserver"

// 创建服务器
const app = createHttpServer({
  port: 8080,
  success: (res) => { console.log('创建成功') },
  fail: (err) => { console.log('创建失败', err.errMsg) },
})

// 注册路由
app.get('/api/hello', (req: HttpRequest) => {
  app.handleRequest(req).json({ msg: "Hello!" })
})

app.post('/api/echo', (req: HttpRequest) => {
  app.handleRequest(req).status(200).json({
    echo: req.body,
    method: req.method,
    path: req.path
  })
})

// 启动服务器
app.start({
  success: () => { console.log('服务器已启动') },
  fail: (err) => { console.log('启动失败', err.errMsg) },
})

二进制响应

send() 支持 ArrayBuffer 参数直接发送二进制数据(仅 uni-app x)。在 uni-app 环境中,需改为发送 base64 编码字符串:

app.get('/api/binary', (req: HttpRequest) => {
  const buf = new ArrayBuffer(16)
  const view = new Uint8Array(buf)
  for (let i = 0; i < 16; i++) {
    view[i] = i
  }
  // #ifdef UNI-APP-X
  app.handleRequest(req)
    .contentType("application/octet-stream")
    .setHeader("Content-Disposition", 'attachment; filename="data.bin"')
    .send(buf)
  // #endif
  // #ifndef UNI-APP-X
  const base64 = uni.arrayBufferToBase64(buf)
  app.handleRequest(req)
    .contentType("text/plain")
    .setHeader("X-Encoding", "base64")
    .send(base64)
  // #endif
})

API

createHttpServer(options)

创建 HTTP 服务器实例。

参数 类型 必填 说明
port number 监听端口 (1-65535)
host string 监听地址,默认 "0.0.0.0"
success function 创建成功回调
fail function 创建失败回调
complete function 完成回调

返回 HttpServerTask 实例。

HttpServerTask

路由注册

// 单方法注册
app.get(path, handler)
app.post(path, handler)
app.put(path, handler)
app.delete(path, handler)
app.patch(path, handler)
app.all(path, handler)     // 匹配所有方法

// 同一路径多方法
app.route('/api/users')
  .get((req) => { app.handleRequest(req).json({ users: [] }) })
  .post((req) => { app.handleRequest(req).status(201).json({ created: true }) })

handleRequest(req)

在路由 handler 中调用,执行中间件链并返回 HttpResponse 对象。

app.get('/api/data', (req: HttpRequest) => {
  app.handleRequest(req)
    .status(200)
    .setHeader('X-Custom', 'value')
    .json({ data: "ok" })
})

HttpResponse 链式方法

方法 说明
status(code) 设置 HTTP 状态码
setHeader(key, value) 设置响应头
contentType(type) 设置 Content-Type
send(body) 发送响应(string | ArrayBuffer | UTSJSONObject)
json(body) 发送 JSON 响应

send() 根据参数类型自动设置默认 Content-Type:

body 类型 默认 Content-Type
string text/plain
ArrayBuffer application/octet-stream
UTSJSONObject application/json

调用 send()json() 后响应自动完成,不可重复调用。

生命周期

// 启动
app.start()
app.start({ success, fail, complete })

// 停止
app.stop()
app.stop({ success, fail, complete })

事件监听

app.onStart((result) => {
  console.log(`服务器启动: ${result.host}:${result.port}`)
})

app.onStop((result) => {
  console.log('服务器已停止')
})

app.onRequest((result) => {
  console.log(`${result.request.method} ${result.request.uri}`)
})

app.onError((result) => {
  console.log(`错误 [${result.phase}]: ${result.errMsg}`)
})

内置中间件

CORS
// 默认配置(允许所有来源)
app.useCors()

// 自定义配置
app.useCors({
  allowOrigin: ["http://localhost:3000", "http://example.com"],
  allowMethods: "GET, POST",
  allowHeaders: "*",
  allowCredentials: true,
  maxAge: 86400
})
静态文件

将文件(HTML、CSS、JS、图片等)预先拷贝到应用私有目录的某个子目录中,然后将该目录绑定到静态文件路由:

// uni-app x
app.useStatic(uni.env.SANDBOX_PATH + 'www', '/static')

// uni-app
app.useStatic('_doc/www', '/static')

访问示例:

  • GET /static/index.html → 读取目录下的 index.html
  • GET /static/css/app.css → 读取目录下的 css/app.css

参数说明:

  • root:文件根目录路径(插件内部会自动转换为原生绝对路径)
  • path(可选):URL 挂载前缀,默认 "/"。请求 URL 去掉此前缀后的部分作为文件相对路径查找

HttpRequest 对象

属性 类型 说明
method string 请求方法
path string 请求路径(不含 query)
uri string 完整 URI(含 query string)
queryParams UTSJSONObject | null 查询参数
headers UTSJSONObject | null 请求头
body string | null 请求体文本
formParams UTSJSONObject | null 表单参数(自动解析 urlencoded)
remoteAddress string 客户端 IP

错误处理

onError 覆盖框架可控的错误:

phase 触发场景
start 服务器启动失败(端口占用等)
middleware 内置中间件执行异常

用户路由 handler 内的错误需自行处理:

app.get('/api/data', (req: HttpRequest) => {
  try {
    const result = doSomething()
    app.handleRequest(req).json({ data: result })
  } catch (e) {
    app.handleRequest(req).status(500).json({ error: e.message })
  }
})

错误码

错误码 说明
9010001 无效的端口号
9010002 无效的根目录路径
9010100 服务器启动失败
9010101 端口已被占用
9010102 服务器未启动
9010103 服务器已在运行
9010200 无效的路由路径
9010201 无效的请求方法
9010900 内部错误

完整示例

import {
  createHttpServer, HttpServerTask, HttpRequest,
  StartServerOptions, StopServerOptions,
  GeneralCallbackResult, HttpServerFail
} from "@/uni_modules/xyz-httpserver"

let app: HttpServerTask | null = null

function startServer(): void {
  app = createHttpServer({
    port: 8080,
    success: (res) => { console.log('createHttpServer: ok') },
    fail: (err) => { console.log(`createHttpServer fail: ${err.errCode} ${err.errMsg}`) },
  })

  // 中间件
  app!.useCors()
  // #ifdef UNI-APP-X
  app!.useStatic(uni.env.SANDBOX_PATH + 'www', '/static')
  // #endif
  // #ifndef UNI-APP-X
  app!.useStatic('_doc/www', '/static')
  // #endif

  // JSON 响应
  app!.get('/api/hello', (req: HttpRequest) => {
    app!.handleRequest(req).json({ msg: "Hello from HTTP Server!" })
  })

  // Echo 请求体
  app!.post('/api/echo', (req: HttpRequest) => {
    app!.handleRequest(req).json({ echo: req.body })
  })

  // 表单解析
  app!.post('/api/form', (req: HttpRequest) => {
    let info = ""
    if (req.formParams != null) {
      // #ifdef UNI-APP-X
      const keys = UTSJSONObject.keys(req.formParams!)
      // #endif
      // #ifndef UNI-APP-X
      const keys = Object.keys(req.formParams!)
      // #endif
      for (let i = 0; i < keys.length; i++) {
        info += `${keys[i]}=${req.formParams![keys[i]] ?? ""} `
      }
    }
    app!.handleRequest(req).json({ received: info })
  })

  // 二进制响应
  // uni-app x: 直接发送 ArrayBuffer
  // uni-app: 发送 base64 编码字符串(客户端需解码)
  app!.get('/api/binary', (req: HttpRequest) => {
    const buf = new ArrayBuffer(16)
    const view = new Uint8Array(buf)
    for (let i = 0; i < 16; i++) {
      view[i] = i
    }
    // #ifdef UNI-APP-X
    app!.handleRequest(req)
      .contentType("application/octet-stream")
      .setHeader("Content-Disposition", 'attachment; filename="test.bin"')
      .send(buf)
    // #endif
    // #ifndef UNI-APP-X
    const base64 = uni.arrayBufferToBase64(buf)
    app!.handleRequest(req)
      .contentType("text/plain")
      .setHeader("X-Encoding", "base64")
      .send(base64)
    // #endif
  })

  // 同一路径多方法
  app!.route('/api/users')
    .get((req: HttpRequest) => {
      app!.handleRequest(req).json({ users: ["user1", "user2"] })
    })
    .post((req: HttpRequest) => {
      app!.handleRequest(req).status(201).json({ created: true })
    })

  // 事件
  app!.onStart((result) => {
    console.log(`Started on ${result.host}:${result.port}`)
  })
  app!.onStop(() => {
    console.log('Stopped')
  })
  app!.onRequest((result) => {
    console.log(`>> ${result.request.method} ${result.request.uri}`)
  })
  app!.onError((result) => {
    console.log(`Error [${result.phase}]: ${result.errMsg}`)
  })

  // 启动
  app!.start({
    success: (res) => { console.log('start: ok') },
    fail: (err) => { console.log(`start fail: ${err.errCode} ${err.errMsg}`) },
  })
}

function stopServer(): void {
  app?.stop()
  app = null
}

隐私、权限声明

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

网络权限

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

插件不采集任何数据

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

许可协议

MIT协议