基于 uWebSockets.js 和 Node.js 构建的高性能病理标本管理后端服务。
Specimen Manager Server 是一个面向病理实验室信息系统的 JSON-over-HTTP REST 风格 API 服务。核心功能包括:
- 用户注册与激活(通过 SMTP 邮件验证)
- Token 认证(UUIDv7 令牌)
- 基于角色的访问控制(位域权限系统)
- 病理标本记录(含患者元数据的增删改查)
- 批次处理追踪(每个记录下包含多个处理阶段子条目)
- 交互式管理 CLI(数据库检查命令)
服务专为高吞吐量设计:HTTP 层采用 uWebSockets.js(C++ 事件驱动 HTTP 服务器,Node.js 绑定),持久层使用 Node.js 内置 node:sqlite 操作 SQLite,响应体支持 Brotli 压缩。
┌─────────────────────────────────────────────────────┐
│ config.js │
│ (server, mailer, logger, data, webui) │
└──────────┬──────────────────────────────────────────┘
│
┌──────────▼──────────┐
│ index.ts │ 入口文件
│ (编排启动 server, │
│ mailer, logger, │
│ commander) │
└──────────┬──────────┘
│
┌─────┴────────────┐
│ │
┌────▼─────┐ ┌───────▼──────┐
│ server.ts│ │ commander.ts │
│ │ │ │
│ 路由注册 │ │ 标准输入 CLI │
│ /v1/* │ │ 管理终端 │
└────┬─────┘ └───────────────┘
│
┌────▼─────────────────────────────────┐
│ src/server/ │
│ ┌──────────────────────────────┐ │
│ │ Handlers (业务逻辑处理) │ │
│ │ user_*.ts / record_*.ts │ │
│ └──────────┬───────────────────┘ │
│ ┌──────────▼───────────────────┐ │
│ │ stmt/ (预编译 SQL 语句) │ │
│ └──────────┬───────────────────┘ │
│ ┌──────────▼───────────────────┐ │
│ │ database/ (建表 + 初始化) │ │
│ └──────────┬───────────────────┘ │
│ ┌──────────▼───────────────────┐ │
│ │ tool/ (权限工具、IP 工具) │ │
│ └──────────────────────────────┘ │
└──────────────────────────────────────┘
每个功能模块独立成文件。server.ts 中的路由处理器负责解析 JSON 请求体、校验参数,然后委托给对应的 handler 模块。Handler 模块实现具体业务逻辑,通过 stmt/ 目录下的预编译 SQL 语句与数据库交互。
| 层级 | 技术 |
|---|---|
| 开发语言 | TypeScript(ESM 模块,.ts 源码) |
| 运行时 | Node.js 22+(依赖内置 node:sqlite 模块) |
| HTTP 服务 | uWebSockets.js(v20.61+,C++ 原生绑定) |
| 数据库 | SQLite,通过 node:sqlite 操作(WAL 模式,两个独立数据库文件) |
| 密码哈希 | @node-rs/argon2(Rust 实现的 Argon2 绑定) |
| 邮件发送 | nodemailer(SMTP,连接池) |
| 日志 | pino(结构化 JSON 日志) |
| UUID | uuid(v7 时间有序 UUID) |
| 打包工具 | rolldown(Rust 实现,输出压缩混淆) |
| 包管理器 | pnpm |
specimen-manager-server/
├── config.js # 全局配置(单文件)
├── package.json # 项目清单 & 脚本
├── pnpm-lock.yaml # 依赖锁定文件
├── rolldown.config.ts # 打包配置
├── src/
│ ├── index.ts # 入口文件
│ ├── server.ts # HTTP 服务 + 路由定义
│ ├── mailer.ts # SMTP 邮件发送器(nodemailer 封装)
│ ├── logger.ts # Pino 日志器(终端 + 文件)
│ ├── commander.ts # 交互式 CLI 命令解析器
│ ├── commander/
│ │ ├── data.ts # 'data' 命令 — 导出数据库表数据
│ │ ├── exit.ts # 'exit' 命令 — 优雅关闭
│ │ └── stop.ts # 'stop' 命令 — 同 exit
│ └── server/
│ ├── check_username.ts # 校验用户名合法性与可用性
│ ├── check_email.ts # 校验邮箱合法性与可用性
│ ├── user_register.ts # 用户注册(→ user_inactive 表)
│ ├── user_active.ts # 账号激活(通过邮件 Token)
│ ├── user_login_username.ts # 用户名 + 密码登录
│ ├── user_login_email.ts # 邮箱 + 密码登录
│ ├── user_logout.ts # Token 失效化(登出)
│ ├── user_select_self.ts # 通过 Token 获取自身信息
│ ├── user_select.ts # 管理员:分页列出用户
│ ├── user_delete.ts # 管理员:按 ID 删除用户
│ ├── user_unregister.ts # 用户自主注销账号
│ ├── user_update_avatar_token.ts # 更新头像 URL
│ ├── user_update_permission.ts # 管理员:修改用户权限
│ ├── userInactive_select.ts # 管理员:查看未激活用户
│ ├── userInactive_delete.ts # 管理员:删除未激活条目
│ ├── send_user_secureToken.ts # 发送密码重置安全令牌邮件
│ ├── user_update_password_secureToken.ts # 通过安全令牌重置密码
│ ├── record_insert.ts # 创建标本记录
│ ├── record_select.ts # 分页列出记录
│ ├── record_delete.ts # 软删除记录(编号回收复用)
│ ├── record_update.ts # 按字段名更新记录
│ ├── recordBatch_insert.ts # 为记录添加批次
│ ├── recordBatch_select.ts # 查看记录下的批次列表
│ ├── recordBatch_delete.ts # 删除批次
│ ├── recordBatch_update.ts # 更新批次状态
│ ├── regex/
│ │ ├── email_valid.ts # 邮箱合法正则
│ │ └── username_invalid.ts # 用户名非法字符正则
│ ├── type/
│ │ ├── result.ts # API 响应码枚举
│ │ └── permission.ts # 权限位域枚举
│ ├── tool/
│ │ ├── has_permission.ts # 检查权限位掩码
│ │ ├── is_permission.ts # 校验权限值合法性
│ │ ├── add_permission.ts # 按位 OR 添加权限标志
│ │ ├── sub_permission.ts # 按位 XOR 移除权限标志
│ │ ├── can_change_permission.ts # 权限修改规则判定
│ │ └── ip_compress.ts # IPv6 地址压缩
│ ├── database/
│ │ ├── user.ts # user.sqlite 建表 + 初始化
│ │ └── record.ts # record.sqlite 建表 + 初始化
│ ├── sql/
│ │ ├── init.ts # PRAGMA 设置(WAL、同步模式等)
│ │ ├── init_user.ts # CREATE TABLE user + root 用户种子
│ │ ├── init_userInactive.ts # CREATE TABLE user_inactive
│ │ └── init_record.ts # CREATE TABLE record、record_batch、record_delete_serial
│ └── stmt/ # 预编译 SQLite 语句(模块级缓存)
│ ├── is_user_username.ts # SELECT 1 FROM user WHERE username = ?
│ ├── is_user_email.ts # SELECT 1 FROM user WHERE email = ?
│ ├── insert_userInactive.ts # INSERT 含重复检查守卫
│ ├── insert_user.ts # 从未激活表迁移到用户表
│ ├── delete_userInactive.ts
│ ├── select_user_password_username.ts
│ ├── select_user_password_email.ts
│ ├── select_user_password_token.ts
│ ├── select_user_token.ts
│ ├── select_user.ts # 分页 SELECT
│ ├── update_user_token_username.ts
│ ├── update_user_token_email.ts
│ ├── update_user_token_token.ts # Token 失效(置换新 Token)
│ ├── update_user_ip_timestamp_token.ts
│ ├── update_user_avatar_token.ts
│ ├── update_user_password_secureToken.ts
│ ├── update_user_permission_id.ts
│ ├── delete_user_id.ts
│ ├── delete_user_token.ts # 自主注销(守卫 id>1)
│ ├── insert_record.ts # 按 part 自增 serial
│ ├── insert_record_serial.ts # 复用已删除的 serial
│ ├── insert_recordBatch.ts
│ ├── insert_recordDeleteSerial.ts
│ ├── delete_record.ts # RETURNING serial, part
│ ├── delete_recordBatch.ts
│ ├── delete_recordDeleteSerial.ts # 弹出最小 serial
│ ├── select_record.ts # 分页
│ ├── select_recordBatch.ts
│ ├── select_recordBatch_recordId.ts
│ ├── select_recordDeleteSerial.ts
│ ├── update_record.ts # 按字段更新
│ └── update_recordBatch.ts
├── runtime/ # 构建输出(gitignore)
├── data/ # SQLite 数据库文件(gitignore)
├── logs/ # 日志文件(gitignore)
└── ssl/ # SSL 证书(gitignore)
注册流程采用两步激活模型:
-
注册(
POST /v1/register):用户提交用户名、邮箱、密码。密码经 Argon2 哈希,生成 UUID 激活令牌,数据写入user_inactive表,同时通过 SMTP 发送激活邮件。 -
激活(
POST /v1/active):用户提供邮件中的激活令牌。数据从user_inactive迁移到user表,账号正式激活。
登录流程支持用户名或邮箱两种方式:
- 客户端提交凭据 → 服务端验证 Argon2 哈希
- 验证通过:生成新的 UUIDv7 Token,存储并在响应中返回
- 客户端后续所有认证请求均携带此 Token
登出:生成新 Token 替换旧 Token,旧 Token 立即失效。
密码重置采用"安全令牌"流程:
/v1/send/secureToken— 向用户邮箱发送安全令牌/v1/update/password/secureToken— 凭令牌重置密码,安全令牌同步更新,旧令牌失效
基于位域(bitfield)的权限模型,包含 4 个基础权限和 4 个管理权限:
| 权限标志 | 位值 | 说明 |
|---|---|---|
SELECT_USER |
1 | 可查看/列出用户 |
UPDATE_USER |
2 | 可删除/修改用户 |
SELECT_RECORD |
4 | 可查看标本记录 |
UPDATE_RECORD |
8 | 可创建/更新/删除记录 |
UPDATE_SELECT_USER |
32 | 可授予/撤销他人的 SELECT_USER |
UPDATE_UPDATE_USER |
64 | 可授予/撤销他人的 UPDATE_USER |
UPDATE_SELECT_RECORD |
128 | 可授予/撤销他人的 SELECT_RECORD |
UPDATE_UPDATE_RECORD |
256 | 可授予/撤销他人的 UPDATE_RECORD |
权限通过按位 OR 组合。root 用户(id=1)拥有 Number.MAX_SAFE_INTEGER(全部标志位激活)。系统强制要求:修改其他用户的某基础权限 X 时,操作者必须持有对应的 UPDATE_X 权限。修改任意 UPDATE_* 权限仅限 root 用户操作。
记录包含完整的患者及病理元数据:
part— 标本分类/类别serial— 按 part 自增的序号(支持删除后回收复用)type— 记录类型remark— 备注信息patient_hospitalization_number— 住院号patient_name、patient_sex、patient_age、patient_birthday— 患者基本信息patient_preoperative_diagnosis、patient_preoperative_biopsy、patient_pathological_diagnosis— 术前诊断、术前活检、病理诊断
序号回收机制:删除记录时,其 (part, serial) 对被推入回收队列。同一 part 下新增记录时优先从回收队列弹出最小的序号复用,避免编号空洞。
批次追踪:每条记录可包含多个批次,每个批次有自增批次号和状态字符串。这对应标本在实验室中经历的不同处理阶段。
服务启动后,标准输入上提供交互式管理终端。支持的命令:
| 命令 | 说明 |
|---|---|
exit / stop |
优雅关闭服务 |
data <表名> <offset> <limit> |
导出指定数据库表的数据行 |
data 命令支持的表名:user、user_inactive、record、record_batch、record_delete_serial。
所有接口均为 POST 请求,请求体为 JSON 格式。所有响应均为 JSON 格式,结构为 { "code": number, "data?": any }。当 Brotli 压缩后的体积更小时,响应体会自动采用 Brotli 压缩。
CORS:所有响应均携带 Access-Control-Allow-Origin: * 头。
| 码 | 枚举名 | 含义 |
|---|---|---|
| 0 | OK |
操作成功 |
| 1 | UNKNOWN |
未知/内部错误 |
| 2 | INVALID |
参数无效或路由不存在 |
| 3 | USERNAME_EXIST |
用户名已被占用 |
| 4 | EMAIL_EXIST |
邮箱已被注册 |
| 5 | PASSWORD_ERROR |
密码错误 |
| 6 | PROMISSION_ERROR |
权限不足 |
| 7 | EMAIL_NOT_EXIST |
系统中不存在该邮箱 |
| 8 | SECURE_TOKEN_HAS_EXPORED |
安全令牌无效或已过期 |
检查用户名是否合法且可用。
{ "username": "string" }
// → { "code": 0 } // 可用
// → { "code": 3 } // 已存在检查邮箱是否合法且可用。
{ "email": "string" }
// → { "code": 0 } // 可用
// → { "code": 4 } // 已存在创建新账号(需通过邮件激活)。
{ "username": "string", "email": "string", "password": "string" }
// → { "code": 0 }使用注册邮件中的令牌激活账号。
{ "token": "string" }
// → { "code": 0 }通过用户名或邮箱登录。
{ "username": "string", "password": "string" }
// 或
{ "email": "string", "password": "string" }
// → { "code": 0, "data": "uuid-v7-token" }使当前 Token 失效。
{ "token": "string" }
// → { "code": 0 }自主注销账号(需密码确认,不可注销 root 用户)。
{ "token": "string", "password": "string" }
// → { "code": 0 }获取当前认证用户的个人信息。
{ "token": "string" }
// → { "code": 0, "data": { "id": 1, "username": "...", "email": "...", "avatar": "...", "permission": 9007199254740991 } }更新用户头像 URL。
{ "token": "string", "avatar": "https://..." }
// → { "code": 0 }向指定邮箱发送密码重置安全令牌。
{ "email": "string" }
// → { "code": 0 }使用安全令牌重置密码。
{ "secure_token": "string", "password": "string" }
// → { "code": 0 }以下接口均需对应权限。
分页列出活跃用户(每页最多 50 条)。需 SELECT_USER 权限。
{ "token": "string", "offset": 0, "total": 50 }
// → { "code": 0, "data": [ { "id": 1, "username": "root", "email": "...", "avatar": "...", "permission": 9007199254740991, "create_timestamp": 1717111111, "login_timestamp": 1717111111, "login_ip": "::1" } ] }按 ID 删除用户(id 必须 ≥ 2,root 用户受保护)。需 UPDATE_USER 权限。
{ "token": "string", "id": 2 }
// → { "code": 0 }分页列出未激活用户。需 SELECT_USER 权限。
{ "token": "string", "offset": 0, "total": 50 }
// → { "code": 0, "data": [...] }通过激活令牌删除未激活用户条目。需 UPDATE_USER 权限。
{ "token": "string", "target_token": "uuid" }
// → { "code": 0 }为用户添加或移除权限标志。需对应的 UPDATE_* 权限。
{ "token": "string", "id": 2, "permission": 1, "add": true }
// → { "code": 0, "data": <新的权限值> }add: true→ 添加标志(按位 OR)add: false→ 移除标志(按位 XOR)
以下接口均需 SELECT_RECORD 或 UPDATE_RECORD 权限。
创建新的标本记录。需 UPDATE_RECORD 权限。
{
"token": "string",
"part": "A",
"remark": "",
"type": "常规",
"patient_hospitalization_number": "H001",
"patient_name": "张三",
"patient_sex": "男",
"patient_age": "45",
"patient_birthday": "1979-01-01",
"patient_preoperative_diagnosis": "...",
"patient_preoperative_biopsy": "...",
"patient_pathological_diagnosis": "..."
}
// → { "code": 0 }创建记录时会自动为该记录创建一个初始批次条目。
分页列出记录(每页最多 50 条)。需 SELECT_RECORD 权限。
{ "token": "string", "offset": 0, "total": 50 }
// → { "code": 0, "data": [ { "id": 1, "part": "A", "serial": 1, "type": "...", "remark": "...", "patient_name": "...", ... } ] }软删除一条记录。其 (part, serial) 将被回收以供后续插入复用。需 UPDATE_RECORD 权限。
{ "token": "string", "id": 1 }
// → { "code": 0 }按字段名更新记录的指定字段。需 UPDATE_RECORD 权限。
{ "token": "string", "id": 1, "key": "patient_name", "value": "李四" }
// → { "code": 0 }支持的 key 值:patient_hospitalization_number、patient_name、patient_sex、patient_age、patient_birthday、patient_preoperative_diagnosis、patient_preoperative_biopsy、patient_pathological_diagnosis。
为记录新增一个处理批次。需 UPDATE_RECORD 权限。
{ "token": "string", "record_id": 1 }
// → { "code": 0 }列出某记录下的所有批次。需 SELECT_RECORD 权限。
{ "token": "string", "record_id": 1 }
// → { "code": 0, "data": [ { "id": 1, "record_id": 1, "batch": 1, "status": "", "create_timestamp": 1717111111, "update_timestamp": 1717111111 } ] }按 ID 删除批次。需 UPDATE_RECORD 权限。
{ "token": "string", "id": 1 }
// → { "code": 0 }更新批次状态字符串。需 UPDATE_RECORD 权限。
{ "token": "string", "id": 1, "status": "已完成" }
// → { "code": 0 }所有配置集中在项目根目录的 config.js 文件中,该文件是一个 ESM 模块,导出默认配置对象。
| 键 | 类型 | 说明 |
|---|---|---|
host |
string |
监听地址。"::" = 所有网卡(IPv4 + IPv6 双栈) |
port |
number |
监听端口(默认:4433) |
key_path |
string |
SSL 私钥路径。留空 = HTTP 模式。启用 HTTPS 需同时设置 key_path 和 cert_path |
cert_path |
string |
SSL 证书路径。留空 = HTTP 模式 |
| 键 | 类型 | 说明 |
|---|---|---|
level |
number |
日志级别:0 = DEBUG、1 = ALERT、2 = ERROR、3 = FATAL |
console |
boolean |
是否输出到终端 |
file_path |
string |
日志文件路径。空字符串表示禁用文件日志 |
| 键 | 类型 | 说明 |
|---|---|---|
option |
object |
Nodemailer 传输选项。包含 host、port、secure、auth、超时和连接池等设置 |
default |
object |
默认邮件选项(如 from 发件地址) |
create_activeMail |
(token: string) => { subject, html } |
激活邮件工厂函数。接收激活令牌,返回邮件标题和 HTML 正文 |
| 键 | 类型 | 说明 |
|---|---|---|
url |
string |
前端地址。用于在激活邮件中生成链接 |
| 键 | 类型 | 说明 |
|---|---|---|
dir |
string |
SQLite 数据库文件存储目录(默认:"./data") |
root.username |
string |
root 管理员用户名 |
root.password |
string |
root 密码(生产环境务必修改!) |
root.email |
string |
root 邮箱地址 |
- 将
config.data.root.password修改为强密码 - 更新
config.mailer.option为真实的 SMTP 凭据 - 将
config.logger.level设为2(ERROR)或3(FATAL) - 将
config.webui.url设置为生产环境前端地址 - 如需 HTTPS,配置
config.server.key_path和config.server.cert_path - 确保
data/和logs/目录存在且可写
- Node.js 22+(必须,依赖内置
node:sqlite模块) - pnpm(推荐)—— 可通过
corepack enable启用
# 安装依赖
pnpm install
# 构建项目(将 src/ 打包为 runtime/index.js)
pnpm build
# 启动服务(需先构建)
pnpm start
# 一键构建并启动
pnpm build-startrolldown.config.ts 将 TypeScript 源码从 src/index.ts 入口打包为单个压缩混淆的 ESM 文件 runtime/index.js。以下包被标记为外部依赖(运行时从 node_modules 加载,不打包):
#config(映射为./config.js)—— 方便修改配置无需重新构建@node-rs/argon2— Rust 原生插件uWebSockets.js— C++ 原生插件pino— 日志库
node runtime/index.js首次运行时,服务会:
- 创建
data/目录和 SQLite 数据库文件 - 使用
config.data.root的凭据初始化 root 用户(id=1) - 验证 SMTP 邮件连接
- 在配置的 host:port 上开始监听
- 在标准输入上显示交互式 CLI 提示符
package.json 中的 imports 字段定义了以下导入快捷方式:
{
"#config": "./config.js",
"#src/*": "./src/*",
"#server/*": "./src/server/*",
"#commander/*": "./src/commander/*"
}| 列名 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PRIMARY KEY AUTOINCREMENT | 用户 ID(1 = root) |
username |
TEXT NOT NULL UNIQUE | 用户名 |
password |
TEXT NOT NULL | Argon2 密码哈希 |
email |
TEXT NOT NULL UNIQUE | 邮箱地址 |
token |
TEXT NOT NULL UNIQUE | 当前认证令牌(UUIDv7) |
secure_token |
TEXT NOT NULL UNIQUE | 密码重置安全令牌 |
avatar |
TEXT NOT NULL | 头像 URL |
permission |
INTEGER NOT NULL | 权限位域 |
create_timestamp |
INTEGER NOT NULL | 账号创建时间戳(Unix 秒) |
create_ip |
TEXT NOT NULL | 注册时 IP 地址 |
login_timestamp |
INTEGER NOT NULL | 最后登录时间戳 |
login_ip |
TEXT NOT NULL | 最后登录 IP |
update_timestamp |
INTEGER NOT NULL | 最后修改时间戳 |
| 列名 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PRIMARY KEY AUTOINCREMENT | 条目 ID |
username |
TEXT NOT NULL UNIQUE | 申请的用户名 |
password |
TEXT NOT NULL | Argon2 密码哈希 |
email |
TEXT NOT NULL UNIQUE | 待验证邮箱 |
token |
TEXT NOT NULL UNIQUE | 激活令牌(UUID) |
create_timestamp |
INTEGER NOT NULL | 注册时间戳 |
create_ip |
TEXT NOT NULL | 注册时 IP |
| 列名 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PRIMARY KEY AUTOINCREMENT | 记录 ID |
part |
TEXT NOT NULL | 标本分类 |
serial |
INTEGER NOT NULL | 序号(按 part 自增) |
remark |
TEXT | 备注 |
type |
TEXT | 记录类型 |
patient_hospitalization_number |
TEXT | 住院号 |
patient_name |
TEXT | 患者姓名 |
patient_sex |
TEXT | 患者性别 |
patient_age |
TEXT | 患者年龄 |
patient_birthday |
TEXT | 患者出生日期 |
patient_preoperative_diagnosis |
TEXT | 术前诊断 |
patient_preoperative_biopsy |
TEXT | 术前活检结果 |
patient_pathological_diagnosis |
TEXT | 病理诊断 |
create_timestamp |
INTEGER NOT NULL | 创建时间戳 |
create_ip |
TEXT NOT NULL | 创建者 IP |
update_timestamp |
INTEGER NOT NULL | 最后更新时间戳 |
update_ip |
TEXT NOT NULL | 最后更新者 IP |
索引:(part, serial DESC),用于高效查询序号。
| 列名 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PRIMARY KEY AUTOINCREMENT | 批次条目 ID |
record_id |
INTEGER NOT NULL | 外键 → record(id) ON DELETE CASCADE |
batch |
INTEGER NOT NULL | 批次号(按记录自增) |
status |
TEXT | 处理状态 |
create_timestamp |
INTEGER NOT NULL | 创建时间戳 |
update_timestamp |
INTEGER NOT NULL | 最后更新时间戳 |
| 列名 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PRIMARY KEY AUTOINCREMENT | 队列条目 ID |
part |
TEXT NOT NULL | 已删除记录的 part |
serial |
INTEGER NOT NULL | 可供复用的序号 |
新插入记录时,优先从该队列中弹出对应 part 的最小序号进行复用。
- 所有密码使用 Argon2(通过
@node-rs/argon2)进行哈希处理(同步变体:hashSync/verifySync) - 系统任何位置均不存储明文密码
- 登录时生成 UUIDv7 令牌用于会话标识
- Token 为时间有序 UUID(v7 规范),兼具随机性和时序性
- 登录会覆盖旧 Token —— 在新设备上登录会使旧会话自动失效
- 登出通过生成新 Token 使当前 Token 失效
- 位域权限控制所有资源访问
- 每个接口在执行前校验 Token 对应的权限值
- root 用户(id=1)受保护:不可删除、其权限检查使用
Number.MAX_SAFE_INTEGER
- 每次登录、注册和数据修改操作均记录客户端 IP 地址(采用 RFC 4291 标准压缩的 IPv6 格式)
- 可选 HTTPS/TLS:当
key_path和cert_path均配置时,通过 uWebSockets.jsSSLApp启用 - 两者均为空时使用 HTTP 模式
MIT © AhMisty