ranuts/node — 迷你 HTTP 框架
一个面向 Node.js 的轻量、零依赖 HTTP 工具集:HTTP 服务器、路由、WebSocket 服务器、body/静态资源中间件,以及一批命令行与文件系统辅助函数。
⚠️ 仅限 Node 环境。 该入口会引入
node:http、node:fs、node:child_process等模块。请从ranuts/node导入,切勿在浏览器代码中使用。
导入
import { Server, Router, staticMiddleware, body } from 'ranuts/node';body 解析中间件的导出名是
body(其内部名称为bodyMiddleware)。 不存在名为bodyMiddleware的导出。
快速开始
import { Server, Router, staticMiddleware, body } from 'ranuts/node';
const app = new Server();
const router = new Router();
// 路由按精确路径匹配,处理函数接收请求 Context。
router.get('/hello', (ctx) => {
ctx.res.setHeader('Content-Type', 'application/json');
ctx.res.end(JSON.stringify({ message: 'hello world' }));
});
// 带 JSON body 的 POST —— body() 会将其解析到 ctx.request.body 上
router.post('/echo', (ctx) => {
ctx.res.end(JSON.stringify({ youSent: ctx.request.body }));
});
// body() 既解析请求体,也会填充 ctx.request(method / path / url / query),
// 路由会读取这些字段 —— 因此必须在 router.routes() 之前注册。
app.use(body());
app.use(router.routes());
app.use(router.allowedMethods());
// 提供静态文件(访问 `/` 时回退到 ./public/index.html)
app.use(staticMiddleware({ pathname: './public' }));
const server = app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});
// `server` 即底层的 node:http Server 实例。中间件顺序很重要:Router 会读取 ctx.request.path 和 ctx.request.method, 而这两个字段由 body() 填充,所以请先注册 body()。内置的 body() 目前解析 application/json 与 multipart/form-data 类型的请求体。
API
Server
默认导出。基于 node:http 的极简 Koa 风格服务器。
| 成员 | 说明 | 类型 |
|---|---|---|
new Server() | 创建服务器,无参数。 | () => Server |
use(middleware) | 向中间件链追加一个中间件。返回 void(不可链式调用)。 | (fn: MiddlewareFunction) => void |
listen(...args) | 开始监听。参数原样转发给 http.Server.listen,返回底层 http.Server。 | (...args) => http.Server |
middleware | 已注册的中间件数组。 | MiddlewareFunction[] |
ctx | 共享的请求 Context(其 req/res 每次请求都会被替换)。 | Context |
中间件签名
type Next = () => Promise<void> | Promise<never>;
type MiddlewareFunction = (ctx: Context, next: Next) => void | Promise<void>;调用 next() 将控制权交给下一个中间件。中间件按注册顺序依次执行;重复调用 next() 会抛出异常。
Context 结构
| 字段 | 说明 | 类型 |
|---|---|---|
req | 传入的请求。 | http.IncomingMessage |
res | 服务器响应。使用 res.setHeader / res.writeHead / res.end 写出。 | http.ServerResponse |
ipv4() | 返回本机第一个非内网 IPv4 地址(否则 undefined)。 | () => string | undefined |
request | 由 body() 添加:{ method, path, url, query, body },其中 query 为 URLSearchParams。 | object(动态) |
[key] | Context 是开放对象,中间件可挂载任意字段。 | any |
Router
默认导出。按 HTTP 方法与精确路径注册处理函数,再通过 routes() 暴露为中间件。
| 方法 | 说明 | 类型 |
|---|---|---|
new Router() | 创建路由实例。 | () => Router |
get(url, handler) | 注册一个 GET 路由。 | (url: string, h: Handler) => void |
post(url, handler) | 注册一个 POST 路由。 | (url: string, h: Handler) => void |
put(url, handler) | 注册一个 PUT 路由。 | (url: string, h: Handler) => void |
patch(url, handler) | 注册一个 PATCH 路由。 | (url: string, h: Handler) => void |
del(url, handler) | 注册一个 DELETE 路由。 | (url: string, h: Handler) => void |
head(url, handler) | 注册一个 HEAD 路由。 | (url: string, h: Handler) => void |
options(url, handler) | 注册一个 OPTIONS 路由。 | (url: string, h: Handler) => void |
routes() | 返回一个将请求派发到匹配处理函数的中间件。 | () => MiddlewareFunction |
allowedMethods() | 返回一个中间件,对未匹配的路径/方法回应 404/405/501。 | () => MiddlewareFunction |
处理函数签名
type Handler = (ctx: Context, next: Next) => void;从 ctx.request 读取请求数据(method、path、url、query、body), 通过 ctx.res 发送响应。路径为精确匹配 —— 不支持 :param 动态段;查询参数 请使用 ctx.request.query。
中间件
| 符号 | 说明 | 类型 |
|---|---|---|
body(options?) | body 解析中间件。填充 ctx.request,并解析 application/json / multipart/form-data。返回一个中间件。 | (o?: Partial<ServerBody>) => MiddlewareFunction |
staticMiddleware(opt?) | 从 opt.pathname(默认 process.cwd())提供静态文件;访问 / 时返回 index.html。 | (o?: Partial<Option>) => MiddlewareFunction |
connect(fn) | 将 Connect/Express 风格的 (req, res, next) 中间件适配为本框架的中间件。 | (fn) => MiddlewareFunction |
body(options) 选项
| 选项 | 说明 | 类型 | 默认值 |
|---|---|---|---|
uploadDir | multipart/form-data 文件上传的存放目录。 | string | '.' |
encoding | 传入请求流的编码。 | BufferEncoding | 'utf-8'/'binary' |
json | 是否解析 JSON body(false 保留原始字符串)。 | boolean | true |
urlencoded | 预留:用于 urlencoded body。 | boolean | true |
staticMiddleware(option) 选项
| 选项 | 说明 | 类型 | 默认值 |
|---|---|---|---|
pathname | 提供文件的根目录。 | string | process.cwd() |
fileTypes | 额外的 扩展名 → MIME 类型 映射。 | Record<string, string> | {} |
WebSocket
| 符号 | 说明 | 类型 |
|---|---|---|
new WSS(httpServer) | 将 WebSocket 服务器附加到 node:http 服务器(处理 upgrade 握手与帧解析)。 | (server: http.Server) => WSS |
import { Server, WSS } from 'ranuts/node';
const app = new Server();
const server = app.listen(3000);
const wss = new WSS(server);
wss.on('connect', (client) => {
client.on('message', (data) => client.send('echo: ' + data));
});
// wss.broadcast(data) 向所有已连接客户端发送;wss.clients 为客户端列表。每个 client 提供 send(data, options?)、ping()、pong()、close()、 socket,以及 message、close、error 事件。
工具函数
| 符号 | 说明 | 签名 |
|---|---|---|
connect(fn) | 将 Connect/Express 的 (req, res, next) 中间件适配为框架中间件。 | (fn) => MiddlewareFunction |
get({ url }) | HTTPS GET 一个 JSON 接口;resolve { success, data, message }。 | ({ url: string }) => Promise<Response> |
getIPAdress() | 本机第一个非内网 IPv4 地址,否则 undefined。 | () => string | undefined |
paresUrl(req) | 将 req.url 解析为 { search, query, pathname, path, href }(注意拼写)。 | (req: IncomingMessage) => ParseUrl | undefined |
prompt({ message }) | 在终端询问 yes/no 问题;输入 y/yes 时 resolve true。 | ({ message, stream?, defaultResponse? }) => Promise<boolean> |
runCommand(cmd, args) | 派生子进程(继承 stdio);退出码为 0 时 resolve。 | (cmd: string, args: string[]) => Promise<void> |
readStream({ path }) | 为 path 创建 fs.ReadStream。 | (o: { path: string, ... }) => ReadStream |
writeStream({ path }) | 为 path 创建 fs.WriteStream。 | (o: { path: string, ... }) => WriteStream |
startTask() | 启动高精度计时器;返回一个不透明的 symbol。 | () => symbol |
taskEnd(symbol) | 自对应 startTask() 起经过的时间(Node 中为纳秒 bigint)。 | (s: symbol) => number | bigint |
traverse(dir, cb, pre?) | 递归遍历 dir,对每个文件调用 cb(relPath, absPath, stats)(异步)。 | (dir, cb, pre?) => Promise<any> |
traverseSync(dir, cb, pre?) | traverse 的同步版本。 | (dir, cb, pre?) => void |
isColorSupported | 布尔值:当前终端是否支持 ANSI 颜色。 | boolean |
colors | ANSI 颜色辅助函数,如 colors.red('text'),另有 reset / bold / dim。 | Record<string, (s: string) => string> |
相关链接
同一个 ranuts/node 入口还提供文件系统辅助函数,另行单独记录: