--- url: /api.md description: Geofront TypeScript API 总览:命名空间、核心类、类型分类及快速入门示例导航。 --- # API 总览 Geofront 的 TypeScript API 通过命名空间 `Geofront` 与类 `GeofrontProxy` 暴露。 ## 快速导航 * [核心类](./core) * [类型与事件](./types-events) * [工具函数与工厂](./utils) ## 最小示例 ```ts import { Geofront } from 'geofront-ts' const proxy = Geofront.createProxy() proxy.setRouter(ctx => ({ target: { host: '127.0.0.1', port: 25565 } })) await proxy.listen({ host: '0.0.0.0', port: 25565 }) ``` *** 继续阅读: [核心类](./core) | [类型与事件](./types-events) | [工具函数](./utils) --- --- url: /examples/hypixel.md description: Hypixel 加速:基于 SOCKS5 上游、连接并发控制与 VIP 动态代理策略的示例。 --- # Hypixel 加速示例 静态白名单 + Host 重写 + MOTD 处理。 ```ts import { Geofront, type RouteContext, type MotdContext } from 'geofront-ts' // 静态白名单:真实生产可换为数据库/HTTP 服务 + 定时刷新 const WHITELIST = new Set(['PlayerOne', 'PlayerTwo', 'Ikaleio']) const proxy = Geofront.createProxy() // 路由:只允许白名单玩家建立游戏连接;重写 host 绕过直连检测 proxy.setRouter((ctx: RouteContext) => { if (!WHITELIST.has(ctx.username)) { return Geofront.disconnect('§c未授权用户无法接入') } // 简易并发控制:同 IP 超过 5 条连接拒绝 if (proxy.getConnectionsByIp(ctx.ip).length > 5) { return Geofront.disconnect('§c该 IP 连接数过多') } return { target: { host: 'mc.hypixel.net', port: 25565 }, rewrite: { host: 'mc.hypixel.net' } } }) // MOTD:展示当前在线与白名单剩余名额;未握手用户名阶段,只能显示全局信息 proxy.setMotdProvider((ctx: MotdContext) => { const active = proxy.getConnectionCount() const maxSlots = WHITELIST.size return { version: { name: 'Hypixel 加速 (WH)' }, players: { max: maxSlots, online: active, sample: [ `§a白名单名额: §e${active}/${maxSlots}`, `§a白名单名额: §e${active}/${maxSlots}` ] }, description: { text: '§6Hypixel 加速代理 §7(Geofront)' } } }) await proxy.listen({ host: '0.0.0.0', port: 25565 }) console.log('Hypixel 加速代理已启动,监听 25565,白名单人数:', WHITELIST.size) // 可选:定期输出简单指标 setInterval(() => { const m = proxy.getMetrics() console.log( '[metrics] active:', m.connections.active, 'totalBytesSent:', m.traffic.totalBytesSent ) }, 10000) ``` --- --- url: /api/connection.md --- --- --- url: /api/motd.md --- --- --- url: /api/proxy.md --- --- --- url: /guide/intro.md --- --- --- url: /api/utils.md description: 工具函数与工厂:快速创建代理、断开、限速转换、简单路由与静态 MOTD 构造器。 --- # 工具函数与工厂 ## Geofront 命名空间 ### createProxy() 创建并返回新的 `GeofrontProxy` 实例。 // 用途:程序主入口处初始化;一个进程通常 1 个实例即可。 ### disconnect(reason: string): never 在 Router 中调用以拒绝玩家: ```ts proxy.setRouter(ctx => { if (!allow(ctx)) return Geofront.disconnect('§c拒绝访问') return { target: { host: '1.2.3.4', port: 25565 } } }) ``` ### rateLimit(uploadMBps?, downloadMBps?, burstMultiplier=2): RateLimit 将 MB/s 转换为字节速率: ```ts Geofront.rateLimit(10, 10) // => { upload:{average:10485760, burst:20971520}, download:{...} } ``` ### simpleRouter(routes: Record\): RouterFn 按 host 精确匹配: ```ts proxy.setRouter( Geofront.simpleRouter({ 'lobby.example.com': { host: '10.0.0.1', port: 25565 }, 'pvp.example.com': { host: '10.0.0.2', port: 25565 } }) ) ``` 未知 host 自动抛出断开。 ### staticMotd(motd): MotdFn 快速构造固定 MOTD: ```ts proxy.setMotdProvider( Geofront.staticMotd({ version: { name: 'Geofront Edge' }, players: { max: 500 }, description: { text: '§aWelcome' } }) ) ``` `protocol` 自动填充为客户端版本。 *** 返回: [API 总览](./) · [核心类](./core) · [类型与事件](./types-events) --- --- url: /examples.md description: 示例总览:最小代理、动态拒绝与限流、缓存策略、SOCKS5 与 PROXY Protocol 组合用法。 --- # 快速示例 ## 简单入口代理 ```ts import { Geofront } from 'geofront-ts' const proxy = Geofront.createProxy() proxy.setRouter(ctx => ({ target: { host: '127.0.0.1', port: 25565 } })) proxy.setMotdProvider(ctx => ({ version: { name: 'Geofront Demo', protocol: ctx.protocol }, players: { max: 100 }, description: { text: '§6Demo Proxy' } })) await proxy.listen({ host: '0.0.0.0', port: 25565 }) ``` ## 动态拒绝与限流 ```ts proxy.setRouter(ctx => { const sameIp = proxy.getConnectionsByIp(ctx.ip) if (sameIp.length > 5) return Geofront.disconnect('§c该 IP 连接过多') return { target: { host: '10.0.0.10', port: 25565 } } }) proxy.setEventHandlers({ onConnectionEstablished: c => { if (!c.player.endsWith('_VIP')) { c.setRateLimit(Geofront.rateLimit(5, 5)) } // ⚠️ 提醒:以玩家名后缀 _VIP 判定仅为演示。生产请使用外部权限查询 + 缓存。 } }) ``` ## 缓存路由与 MOTD ```ts proxy.setRouter(ctx => ({ target: { host: '10.0.0.5', port: 25565 }, cache: { granularity: 'ip+host', ttl: 60_000 } })) proxy.setMotdProvider(ctx => ({ version: { name: 'Edge Entry' }, players: { max: 500 }, description: { text: '§a高速接入' }, cache: { granularity: 'ip', ttl: 5_000 } })) ``` ## SOCKS5 + PROXY Protocol ```ts proxy.setRouter(ctx => ({ target: { host: 'mc.hypixel.net', port: 25565 }, proxy: { url: 'socks5://proxy.example.com:1080' }, proxyProtocol: 1, rewrite: { host: 'mc.hypixel.net' } })) ``` 更多: [Hypixel 加速](./hypixel) · [速率限制策略](./rate-limit) · [缓存路由与 MOTD](./cache) --- --- url: /guide/architecture.md description: Geofront 内部架构:Rust 核心、FFI 轮询、路由与 MOTD 缓存、速率限制、零拷贝与指标系统详解。 --- # 架构设计 ## 总览 Geofront 分为三层: 1. Rust 核心 (I/O + 协议 + 性能) 2. FFI 桥接 (Bun FFI 符号,JSON 交互) 3. TypeScript API (面向用户的对象与回调模型) ```text Client ──▶ [Rust Listener] ──▶ Handshake 解析 ──┬─▶ (状态请求) MOTD 流程 │ └─▶ (登录) 路由流程 → 后端连接 → 数据转发 ``` ## Rust 核心模块 | 模块 | 职责 | | --------------- | -------------------------------------------------------------------------------------------------------- | | `connection.rs` | 连接生命周期、握手解析、路由调用、MOTD、上游代理、数据转发、PROXY protocol、速率限制应用、零拷贝 (Linux) | | `protocol.rs` | Minecraft 协议最小解析工具:握手、登录开始、VarInt、状态/延迟回复、断开包写入 | | `splice.rs` | Linux 下基于 `splice()` 的零拷贝双向转发,减少用户态缓冲复制 | | `cache.rs` | 路由与 MOTD 统一缓存;支持 IP / IP+Host 粒度、拒绝缓存、TTL、统计 | | `state.rs` | 全局状态:连接计数、速率限制器、事件队列、挂起回调、异步运行时、缓存实例 | | `types.rs` | 序列化结构、枚举、缓存配置、Metrics 快照、FFI JSON 模型 | | `ffi.rs` | Bun 侧 dlopen 的符号导出与 JSON 数据传递接口 | | `logging.rs` | tracing 初始化,支持环境过滤与动态重载 | ## 连接处理流水线 1. 接受 TCP 连接 → 分配 `conn_id` 2. 可选解析 PROXY protocol v1/v2(严格模式下失败即断开) 3. 读取握手包 → 判定 next\_state: * `1` → 状态 / MOTD 流程 * `2` → 登录 / 需要继续读取登录开始与用户名 4. 状态请求:进入 MOTD 决策(缓存 → 回调 → 构建 JSON → 发送) 5. 登录:路由缓存检查 → 提交路由请求(队列)→ 等待 JS 决策 → 可选重写 host → 建立后端连接(支持 SOCKS5) 6. 可选写入 PROXY protocol 头到后端(路由结果决定) 7. 回放握手+登录开始到后端 8. 进入双向转发阶段: * Linux: `splice::copy_bidirectional` 优先 * 其他平台: 自定义 `copy_bidirectional_fallback` 9. 循环中分块读写 + 令牌桶速率限制 + Metrics 原子累加 10. 关闭时写入断开事件队列,由 TS 轮询抽取触发 `onConnectionClosed` ## 事件与轮询模型 Rust 不直接回调 JS,而是采用“批量轮询”模式以减少跨语言边界频率: * Rust 收集:`ROUTE_REQUEST_QUEUE` / `MOTD_REQUEST_QUEUE` / `DISCONNECTION_EVENT_QUEUE` * TypeScript 定时 `proxy_poll_events` (默认 10ms) 获取批量 JSON: ```json { "routeRequests": [ { "connId": 1, "peerIp": "...", ... } ], "motdRequests": [ ... ], "disconnectionEvents": [ { "connId": 1 } ] } ``` * TS 逐条处理: * 路由:执行用户设置的 `routerCallback`,建立 `Connection` 对象,提交决策 JSON * MOTD:执行 `motdCallback` 或默认构造 * 断开:移除缓存连接对象,触发关闭事件 这种模式的优势: * 减少 FFI 调用开销 * 无需在 Rust 持有 JS 函数指针,避免生命周期/GC 问题 * 批量处理 + JSON 内存复用 ## 路由与 MOTD 决策结构 TS 回调返回的新式结构: ```ts interface RouteResult { target: { host: string; port: number } proxy?: { url: string } proxyProtocol?: 1 | 2 // 向后端写入 PROXY Protocol 版本(v1 或 v2) rewrite?: { host: string } cache?: { granularity: 'ip' | 'ip+host' ttl: number reject?: boolean rejectReason?: string } } ``` 内部兼容旧格式并序列化为: ```json { "remoteHost": "1.2.3.4", "remotePort": 25565, "proxy": "socks5://...", "proxyProtocol": 1, "rewriteHost": "backend.internal", "cache": { "granularity": "ipHost", "ttl": 60000 } } ``` MOTD 回调返回: ```ts interface MotdResult { version: { name: string; protocol?: number } players: { max: number online?: number sample?: Array<{ name: string; id: string } | string> } description: { text: string } favicon?: string cache?: { granularity: 'ip' | 'ip+host' ttl: number reject?: boolean rejectReason?: string } } ``` `online` / `protocol` 支持自动填充 (`auto` 语义在内部处理)。 ## 缓存层设计 * 基于 `DashMap`(多线程安全),键格式: * IP: `ip:` * IP+Host: `ip::host:` * 条目:`{ data: Value, is_rejection, reject_reason, expires_at }` * TTL 以毫秒存储,过期访问时懒删除 * 路由与 MOTD 使用同一缓存:减少重复逻辑,提高命中 * 拒绝决策可缓存,防止重复高频恶意访问 ### 典型缓存策略举例 ```ts proxy.setRouter(ctx => ({ target: { host: '10.0.0.5', port: 25565 }, cache: { granularity: 'ip+host', ttl: 30_000 } })) proxy.setMotdProvider(ctx => ({ version: { name: 'Edge Entry' }, players: { max: 200 }, description: { text: '§a欢迎' }, cache: { granularity: 'ip', ttl: 5_000 } })) ``` ## 速率限制 * 使用 `governor` 提供两个独立令牌桶(发送/接收) * `Geofront.rateLimit(uploadMBps, downloadMBps, burstMultiplier)` 返回平均/突发字节速率 * 设置顺序: 1. 全局:`setGlobalRateLimit`(应用到后续每个新连接) 2. 单连接:`connection.setRateLimit` * 转发循环中按 4096 字节块申请令牌 ### 示例 ```ts proxy.setEventHandlers({ onConnectionEstablished: c => { if (c.player.endsWith('_VIP')) { c.setRateLimit(Geofront.rateLimit(50, 50)) } else { c.setRateLimit(Geofront.rateLimit(10, 10)) } } }) // ⚠️ 注意:以上依据玩家名后缀判断 VIP 仅为教学示意。 // 正确实践:外部权限/会员系统 -> 短 TTL 缓存 -> 失败回退默认限速。 ``` ## 零拷贝转发 * 仅 Linux:尝试把 outbound downcast 为 `TcpStream`,若成功 → `splice::copy_bidirectional` * 其他平台或非 TCP → 回退自定义复制循环 * Metrics 在零拷贝路径结束后统一加总 ## 指标 (Metrics) Rust 层维护: * 全局:`TOTAL_CONN`, `ACTIVE_CONN`, `TOTAL_BYTES_SENT`, `TOTAL_BYTES_RECV` * 单连接:`ConnMetrics { bytes_sent, bytes_recv }` TS 层: * 通过 `proxy_get_metrics` 获取 JSON → 转换为: ```ts interface GlobalMetrics { connections: { total: number; active: number } traffic: { totalBytesSent: number; totalBytesReceived: number } } ``` * 连接级指标采用轮询缓存 `connectionMetricsCache` ## FFI 设计要点 * 所有跨语言复杂对象 → JSON 字符串 + C 字符串指针 * 统一释放:`proxy_free_string` * 批量事件:`proxy_poll_events` → 减少 syscall/FFI 调用 * 关键导出符号(节选): * `proxy_start_listener(host, port)` * `proxy_submit_routing_decision(connId, json)` * `proxy_submit_motd_decision(connId, json)` * `proxy_get_metrics()` * `proxy_set_rate_limit(connId, sendAvg, sendBurst, recvAvg, recvBurst)` * `proxy_cleanup_cache()` / `proxy_get_cache_stats()` ## TypeScript API 层对象模型 | 对象 | 说明 | | ---------------------- | -------------------------------------------------------------------------------------- | | `GeofrontProxy` | 主控制器:管理监听器、连接、回调、全局限速、缓存、事件轮询 | | `Listener` | 监听实例;`stop()` 停止;`isListening()` 查询状态 | | `Connection` | 活跃连接的快照与操作:断开、限速、Metrics、存续时间 | | `Geofront` (namespace) | 工厂与工具:`createProxy` / `disconnect` / `rateLimit` / `simpleRouter` / `staticMotd` | ## 事件生命周期 | 事件 | 触发时机 | | ----------------------------- | ----------------------------------------------- | | `onConnectionEstablished` | 路由决策成功并已加入连接表 | | `onConnectionClosed` | Rust 记录断开 → 队列 → TS 轮询处理并从 Map 移除 | | `onListenerStarted / Stopped` | 监听器启动/停止操作成功后 | | `onError` | 轮询解析、metrics 更新或内部异常捕获时 | ## 错误与断开策略 * 路由中抛出 `Geofront.disconnect(reason)` → 转换为 `DisconnectError` → 生成 `{ disconnect: reason }` * MOTD / Route 若异常:返回统一 `Internal ... error` 文案 * 可缓存拒绝:`cache.reject = true` + `rejectReason` ## 设计取舍 | 场景 | 选择 | 原因 | | -------------- | ---------------- | ------------------------------ | | Rust ↔ JS 通信 | 批量轮询 + JSON | 简化生命周期,避免持久回调句柄 | | 限速实现 | 用户态令牌桶 | 精细控制 + 跨平台一致性 | | 零拷贝 | Linux `splice()` | 最大化常见部署环境性能 | | 缓存粒度 | IP / IP+Host | 平衡命中率与内存 | | 拒绝缓存 | 支持 | 过滤恶意或非法请求成本下降 | ## 未来可拓展方向 * Web UI / Prometheus 指标导出 * 动态热更新 Router(无需重启) * 多监听器多端口协同调度策略 * 多层次限速(全局 / group / 每 IP) * QUIC / Bedrock 支持 (实验性) *** ### 术语速览 * GeofrontProxy: 用户主控制器。不要臆造其不存在的方法。 * Listener: 由 `listen()` 返回的对象,负责特定 host/port 监听。 * Connection: 已成功路由并处于转发阶段的连接抽象。 * RouteContext / MotdContext: 回调输入;包含 ip / host / username / protocol。 * RouteResult: 路由决策;必须包含 target,其他字段可选。 * Cache granularity: 'ip' 或 'ip+host';决定缓存 key 组成。 * Reject cache: 带 `cache.reject=true` 的路由/MOTD 结果,用于缓存拒绝原因。 * RateLimit: 上传/下载两组令牌桶字节速率与可选突发。 * Metrics: 全局或连接级字节累加统计。 * DisconnectError: 由 `Geofront.disconnect()` 抛出用于优雅拒绝。 ### 回答策略 1. 若用户询问 API,优先引用已存在的公开方法或接口定义;不要创造新字段。 2. 涉及路由或 MOTD 返回结构时,列出 `target` / `proxy` / `rewrite` / `cache` / `reject` 相关真实字段。 3. 速率限制回答须说明上传与下载分别可配;使用 `Geofront.rateLimit()` 生成字节速率对象。 4. 缓存问题回答需指出路由与 MOTD 共用同一缓存实现,支持拒绝缓存与 TTL、粒度。 5. 不要引用 README 过时描述;一切以源码 / 本文档定义为准。 6. 如问题含糊,先澄清所指对象(路由? MOTD? 连接?)再给出具体 API。 7. 性能相关回答可提示 Linux 使用 splice 零拷贝,其它平台走回退复制。 8. 若用户尝试获取玩家数量,推荐 `getPlayerCount()`;获取活跃连接用 `getConnectionCount()`。 9. 错误处理:说明 `Geofront.disconnect()` 只在路由阶段生效,并被转为断开响应。 10. Vercel 部署触发条件:只有 commit message 以 `docs:` 开头才应构建(来自脚本)。 ### 禁止项 * 不要发明协议版本处理逻辑之外的字段。 * 不要建议直接操作内部 FFI 符号;使用封装 API。 * 不要将缓存粒度扩展为未定义的枚举,例如 'player'。 *** 返回:[首页](/) · [API 文档](/api/) · [示例](/examples/) --- --- url: /api/core.md description: 核心类:GeofrontProxy、Listener、Connection 的职责、管理与生命周期方法详解。 --- # 核心类 ## GeofrontProxy 通过 `Geofront.createProxy()` 创建。实例内部会: * 动态加载 Rust FFI 动态库(依据 `NODE_ENV` 选择 debug / dist) * 开启事件轮询 (默认 10ms) * 开启 metrics 轮询 (默认 1000ms) ### 配置方法 > 何时使用:在应用启动或热更新阶段替换回调/策略;这些方法是声明式注册点,不会立即触发网络行为。 | 方法 | 描述 | | ------------------------------------------------- | ---------------------------------------------------------- | | `setRouter(router: RouterFn): this` | 设置路由回调(可返回 Promise)。 | | `setMotdProvider(provider: MotdFn): this` | 设置 MOTD 生成器。 | | `setGlobalRateLimit(limit: RateLimit): this` | 设置全局默认速率限制,自动应用到新连接并立即更新现有连接。 | | `setEventHandlers(handlers: EventHandlers): this` | 绑定事件。 | ### 监听器管理 > 作用:对外暴露接入点。可以按需开多个端口(如不同 Proxy Protocol / 不同地域入口)。 | 方法 | 描述 | | ------------------------------------------------ | -------------------------------------------------------------------------------------- | | `listen(config: ProxyConfig): Promise` | 启动监听器并返回 `Listener`。支持 `proxyProtocol` ('none' | 'optional' | 'strict')。 | | `getListeners(): ReadonlyArray` | 获取当前所有监听器。 | | `stopAllListeners(): Promise` | 停止全部监听器。 | ### 连接管理 > 典型场景:实时封禁、统计在线、按 IP/玩家做限流、运维脚本扫描异常连接。 | 方法 | 描述 | | ----------------------------------- | -------------------------- | | `getConnections()` | 获取活跃连接对象数组。 | | `getConnection(id)` | 获取特定连接。 | | `getConnectionsByPlayer(player)` | 按玩家名过滤。 | | `getConnectionsByIp(ip)` | 按来源 IP 过滤。 | | `getConnectionsByHost(host)` | 按握手主机过滤。 | | `disconnectAll(reason?)` | 断开全部(返回断开数量)。 | | `disconnectPlayer(player, reason?)` | 断开某玩家全部连接。 | | `disconnectIp(ip, reason?)` | 断开某 IP 全部连接。 | ### 统计与列表 > 适合低频(秒级)采样输出或上报监控;不是逐包实时计数接口。 | 方法 | 描述 | | ----------------------------- | ------------------------------ | | `getMetrics(): GlobalMetrics` | 获取一次快照(内部立即 FFI)。 | | `getConnectionCount()` | 当前连接数量(Map size)。 | | `getPlayerCount()` | 去重玩家数。 | | `getActivePlayerList()` | 返回活跃玩家列表。 | ### 生命周期 > 推荐流程:收到退出信号 -> `disconnectAll` (可选) -> `shutdown` -> 进程退出;确保释放 FFI 资源与监听端口。 | 方法 | 描述 | | ----------------- | ------------------------------------ | | `shutdown()` | 停止轮询、关闭监听器、清空内部状态。 | | `isShutdown()` | 是否处于关闭流程。 | | `cleanupCache()` | 主动清理过期缓存。 | | `getCacheStats()` | `{ totalEntries, expiredEntries }`。 | ### 内部行为(说明性) * `updateMetrics()` 会刷新全局与每连接缓存指标 * 事件轮询获得:路由请求 / MOTD 请求 / 断开事件 * 新连接成功路由后才创建 `Connection` 对象 ## Listener | 成员 / 方法 | 描述 | | --------------------- | -------------------------------------- | | `id: number` | 唯一监听器 ID。 | | `config: ProxyConfig` | 启动时配置的 host/port/proxyProtocol。 | | `stop()` | 停止当前监听器。 | | `isListening()` | 是否仍存在于 `getListeners()`。 | ## Connection | 成员 / 方法 | 描述 | | -------------------------------------------------------------- | ------------------------------------------------------------ | | `id` / `player` / `ip` / `host` / `protocol` / `startAt: Date` | 基本元数据。 | | `getMetrics()` | 返回累计字节数 `{ bytesSent, bytesReceived }`(来自缓存)。 | | `setRateLimit(limit)` | 设置独立速率限制。 | | `disconnect(reason?)` | 断开连接(当前未直接传递 reason 到服务端,由路由阶段控制)。 | | `isActive()` | 查询是否仍在连接 Map 中。 | | `getDuration()` | 存续毫秒数。 | | `getDurationString()` | 人类友好持续时间字符串。 | *** 继续: [类型与事件](./types-events) --- --- url: /api/types-events.md description: API 类型与事件:配置、路由/MOTD 上下文与结果、限速、指标、回调与事件处理器定义。 --- # 类型与事件 ## 基础类型 ### ProxyConfig ```ts interface ProxyConfig { host: string port: number proxyProtocol?: 'none' | 'optional' | 'strict' } // 用途:listen() 的配置;可通过 multiple listen 启动多入口。 ``` ### RouteContext & RouteResult ```ts interface RouteContext { ip: string host: string username: string protocol: number } // 用途:只包含决定路由所需最小信息;可以基于 host / ip / username 做分流与限流判定。 interface RouteResult { target: { host: string; port: number } proxy?: { url: string } proxyProtocol?: 1 | 2 rewrite?: { host: string } cache?: { granularity: 'ip' | 'ip+host' ttl: number reject?: boolean rejectReason?: string } } // 用途:返回给底层核心的转发表达;cache 字段可短暂记忆相同条件决策减少 JS 往返。 ``` ### MotdContext & MotdResult ```ts interface MotdContext { ip: string host: string protocol: number } // 用途:查询阶段(未握手玩家名),用于生成 MOTD 与伪在线信息。 interface MotdResult { version: { name: string; protocol?: number } players: { max: number online?: number sample?: Array<{ name: string; id: string } | string> } description: { text: string } favicon?: string cache?: { granularity: 'ip' | 'ip+host' ttl: number reject?: boolean rejectReason?: string } } ``` ### RateLimit ```ts interface RateLimit { upload?: { average: number; burst?: number } download?: { average: number; burst?: number } } ``` 字节/秒单位;`Geofront.rateLimit` 提供 MB/s 转换简化调用。 ### Metrics ```ts interface ConnectionMetrics { bytesSent: number bytesReceived: number } interface GlobalMetrics { connections: { total: number; active: number } traffic: { totalBytesSent: number; totalBytesReceived: number } } ``` ### ConnectionInfo ```ts interface ConnectionInfo { id: number player: string ip: string host: string protocol: number startAt: Date } ``` ## 回调函数类型 ```ts type RouterFn = (ctx: RouteContext) => RouteResult | Promise type MotdFn = (ctx: MotdContext) => MotdResult | Promise ``` ## 事件处理器 ```ts interface EventHandlers { onConnectionEstablished?: (c: Connection) => void onConnectionClosed?: (c: Connection, info: ConnectionInfo) => void onListenerStarted?: (l: Listener) => void onListenerStopped?: (l: Listener) => void onError?: (err: Error) => void } ``` ## 错误类型 `DisconnectError`:内部用于路由阶段中断流程;由 `Geofront.disconnect()` 抛出并被捕获转换为 `{ disconnect: reason }`。 *** 继续: [工具函数](./utils) --- --- url: /examples/cache.md description: 缓存策略:路由与 MOTD 共享缓存、拒绝缓存、粒度 (ip / ip+host) 与统计维护示例。 --- # 缓存路由与 MOTD ## 缓存路由结果 ```ts proxy.setRouter(ctx => ({ target: { host: '10.0.0.5', port: 25565 }, cache: { granularity: 'ip+host', ttl: 60_000 } })) ``` ## 缓存 MOTD ```ts proxy.setMotdProvider(ctx => ({ version: { name: 'Edge Entry' }, players: { max: 300 }, description: { text: '§a欢迎' }, cache: { granularity: 'ip', ttl: 5_000 } })) ``` ## 缓存拒绝策略 ```ts proxy.setRouter(ctx => ({ target: { host: '10.0.0.9', port: 25565 }, cache: { granularity: 'ip', ttl: 120_000, reject: true, rejectReason: 'Blocked region' } })) ``` > 当 `reject: true` 时,`data` 仍会缓存,并在相同粒度匹配时直接断开,减少回调执行。 ## 监控缓存 ```ts proxy.cleanupCache() // 主动清理过期项 const stats = proxy.getCacheStats() // { totalEntries, expiredEntries } ``` --- --- url: /examples/rate-limit.md description: 速率限制:全局默认、按玩家分级与基于实时传输量的动态降速策略示例。 --- # 速率限制策略 ## 全局默认限速 ```ts proxy.setGlobalRateLimit(Geofront.rateLimit(10, 10)) ``` ## 按用户分级 ```ts proxy.setEventHandlers({ onConnectionEstablished: c => { if (c.player.startsWith('vip_')) { c.setRateLimit(Geofront.rateLimit(50, 50)) } else if (c.player.startsWith('premium_')) { c.setRateLimit(Geofront.rateLimit(100, 100)) } else { c.setRateLimit(Geofront.rateLimit(10, 10)) } // ⚠️ 提示:基于名字前缀 (vip_/premium_) 的等级判定易被伪造,仅用于示例。 // 生产:外部会员/订单系统 -> 缓存 (60s) -> 设置限速;失败回退基础档。 } }) ``` ## 动态调节大流量连接 ```ts setInterval(() => { for (const c of proxy.getConnections()) { const m = c.getMetrics() const total = m.bytesSent + m.bytesReceived if (total > 100 * 1024 * 1024) { c.setRateLimit(Geofront.rateLimit(1, 1)) } } }, 10_000) ```