esbuker/elysia-nazli

GitHub: esbuker/elysia-nazli

为运行在 Bun 上的 Elysia 应用提供轻量级、可精细化配置的速率限制插件。

Stars: 1 | Forks: 0

# elysia-nazli [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/esbuker/elysia-nazli/actions/workflows/ci.yml) [![Bundle size (gzip)](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fesbuker%2Felysia-nazli%2Fmaster%2F.github%2Fbundle-size.json&query=%24.gzip&label=bundle%20%28gzip%29&logo=github)](https://github.com/esbuker/elysia-nazli/blob/master/.github/bundle-size.json) 为运行在 [Bun](https://bun.sh) 上的 [Elysia](https://elysiajs.com) 应用提供的轻量级、优雅的速率限制。 `elysia-nazli` 的入门非常简单:添加一个限制,保护你的路由,然后继续开发。当你的 API 需要更精细的控制时,它可以通过路由规则、组合 key、共享存储和更平滑的算法与你一起成长。 专为单个全局限制无法满足需求的实际服务而构建。 ## 目录 - [为什么使用它](#why-use-it) - [功能](#features) - [快速开始](#quick-start) - [安装说明](#installation) - [使用示例](#usage-examples) - [兼容性](#compatibility) - [文档](#documentation) - [开发](#development) - [贡献](#contributing) ## 为什么使用它 当你的 Elysia 应用需要配置清晰且对真实流量足够严格的速率限制时,请使用 `elysia-nazli`: - 只需几行代码即可设置一个全局限制作为起点。 - 为登录、注册、webhook 或昂贵的 endpoint 添加更严格的限制。 - 选择如何识别客户端:IP、用户 id、header、自定义逻辑或组合 key。 - 将状态保存在内存、SQLite、Redis 或你自己的 store 中。 - 决定当后端 store 缓慢或不可用时 API 的行为方式。 ## 功能 - **全局、前缀和路由规则**,支持字符串或 `RegExp` 路径 - **Elysia 路由选项**支持 `{ rateLimit: { ... } }` - **人类可读的时长字符串**,例如 `'30s'`、`'15m'`、`'2h'`,以及数字毫秒 - **感知 method 的限制**,适用于路由和前缀规则 - **算法:** fixed-window、sliding-window、token-bucket 和 GCRA - **Key 解析器:** `ip`、`user`、`header`、`bodyField`、`firstOf`、`compose`、`hmac` 和 `custom` - **Ban 窗口**,用于更严格的滥用处理 - **标准与 legacy headers**,支持按规则覆盖 - **存储:** 内存、SQLite、Redis 和自定义 `RateLimitStore` 实现 - **生产环境控制:** 按路由设置 store、fallback store、store 超时和失败策略 ## 快速开始 安装该包: ``` bun add elysia-nazli ``` 添加一个全局 limiter: ``` import { Elysia } from 'elysia' import { rateLimit } from 'elysia-nazli' const app = new Elysia() .use( rateLimit({ limit: 120, window: '1m', }), ) .get('/', () => 'ok') .listen(3000) ``` 这允许每个客户端 key 每分钟 120 次请求。默认算法是 `fixed-window`,默认 store 是内存,并且启用了标准的 `ratelimit-*` headers。 ## 安装说明 ``` bun add elysia-nazli ``` Peer dependency: ``` bun add elysia ``` Redis 和 SQLite 辅助工具可通过 subpath exports 获取: ``` import { redisStore } from 'elysia-nazli/redis' import { sqliteStore } from 'elysia-nazli/sqlite' ``` ## 使用示例 ### 全局加登录保护 ``` import { Elysia } from 'elysia' import { rateLimit } from 'elysia-nazli' const app = new Elysia() .use( rateLimit({ namespace: 'my-api', limit: 120, window: '1m', routes: { 'POST /login': { limit: 10, window: '15m', ban: '5m', }, }, }), ) .post('/login', () => 'ok') ``` `/login` 路由必须同时通过全局规则和路由规则。 ### 将限制保持在路由旁边 ``` import { Elysia } from 'elysia' import { rateLimit } from 'elysia-nazli' const app = new Elysia() .use(rateLimit()) .post('/login', () => 'ok', { rateLimit: { limit: 10, window: '15m', ban: '5m', }, }) ``` 当关注局部可读性时使用路由选项。当你需要早期的 `onRequest` 限制、对象映射、`RegExp` 路径,或者需要一起评估多个匹配的规则时,请使用插件级别的 `routes`。 ### 使用 Redis 和特定于规则的 key ``` import { RedisClient } from 'bun' import { Elysia } from 'elysia' import { bodyField, firstOf, ip, rateLimit, user } from 'elysia-nazli' import { redisStore } from 'elysia-nazli/redis' const redis = new RedisClient('redis://localhost:6379') const app = new Elysia().use( rateLimit({ algorithm: 'gcra', key: firstOf(user('id'), ip({ trustedProxyDepth: 1 })), store: redisStore({ client: redis, adapter: 'bun', prefix: 'myapp' }), limit: 120, window: '1m', headers: { standard: true, legacy: false, }, routes: { 'POST /login': { limit: 10, window: '15m', ban: '5m', key: bodyField('email', { normalize: 'email', hmacSecret: Bun.env.RATE_LIMIT_KEY_SECRET!, }), }, }, }), ) ``` ### 为每个路由使用不同的 store ``` import { memoryStore, rateLimit } from 'elysia-nazli' import { sqliteStore } from 'elysia-nazli/sqlite' rateLimit({ store: memoryStore(), limit: 120, window: '1m', routes: { 'POST /login': { limit: 10, window: '15m', store: sqliteStore('./limits.sqlite'), }, }, }) ``` ## 兼容性 - **Runtime:** Bun `>=1.3.13` - **框架:** Elysia `^1.4.0` - **Node.js:** 不是受支持的 runtime 目标 该包是 Bun 优先的。默认导入保持轻量,而 Redis 和 SQLite 辅助工具则位于 `elysia-nazli/redis` 和 `elysia-nazli/sqlite` 之后。 ## 文档 | 指南 | 用途 | | -------------------------------------------------- | ----------------------------------------------------------- | | [文档索引](./docs/README.md) | 快速找到合适的指南 | | [示例与模式](./docs/examples.md) | 常见设置、登录保护、代理安全 IP | | [配置参考](./docs/configuration.md) | 选项、默认值、验证、headers、路由宏 | | [Store 与后端](./docs/stores.md) | 内存、SQLite、Redis、自定义 store | | [算法与语义](./docs/algorithm.md) | 算法权衡、规则匹配、ban、成本 | | [生产与弹性](./docs/production.md) | 失败策略、fallback store、超时、代理、扩展 | ## 开发 ``` bun install bun run typecheck bun run test bun run build ``` 实用脚本: | 命令 | 作用 | | -------------------------- | ----------------------------------------------- | | `bun run test` | 运行测试套件 | | `bun run test:integration` | 运行集成测试 | | `bun run typecheck` | 检查 TypeScript 但不生成文件 | | `bun run lint` | 运行 ESLint | | `bun run format:check` | 检查 Prettier 格式 | | `bun run build` | 构建 JS、声明和 bundle size 报告 | | `bun run bench` | 运行本地基准测试 | | `bun run bench:compare` | 比较 Elysia 插件请求路径吞吐量 | | `bun run release:check` | 运行类型检查、测试和构建 | ## 贡献 欢迎提交关于 bug、安全复现案例和聚焦的功能讨论的 Issue。目前不接受外部 pull request。 在打开 issue 之前,请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md) 和 [SECURITY.md](./SECURITY.md)。 ## 许可证 [MIT](./LICENSE)
标签:API保护, Bun, Elysia, Syscall, Web开发, 中间件, 搜索引擎查询, 自动化攻击, 限流