API 参考

📚 目录


RateLimiter 类

构造函数

const limiter = new RateLimiter(options);

方法

check(key, options)

检查请求是否在限流内。

const result = await limiter.check('user-123', { route: '/api/data' });

// result 对象包含:
// {
//   allowed: boolean,      // 是否允许请求
//   limit: number,         // 限制数
//   current: number,       // 当前计数
//   remaining: number,     // 剩余请求数
//   resetTime: number,     // 重置时间(毫秒)
//   retryAfter: number,    // 重试等待时间(毫秒)
// }

middleware()

创建 Express 风格的 (req, res, next) 中间件函数。Koa、Egg.js、Fastify、Hapi 等框架建议使用 check() 按各自的请求/响应语义封装适配器。

const middleware = limiter.middleware();

// Express
app.use(middleware);

// Koa / Egg.js / Fastify / Hapi
// 使用 limiter.check(key, { route }) 在框架中间件、hook 或 pre-handler 中封装

reset(key)

重置特定键的限制计数。

await limiter.reset('user-123');

resetAll()

重置所有键的限制计数。

await limiter.resetAll();

close()

关闭当前 limiter 拥有的存储资源。store: 'redis://...' 创建的 Redis client 会在这里关闭;外部传入的 Redis client 默认仍由调用方管理。

await limiter.close();

配置选项速查

选项类型默认值说明
windowMsnumber60000时间窗口大小,单位毫秒
maxnumber | function100最大请求数,支持按请求动态计算
algorithm'sliding-window' | 'fixed-window' | 'token-bucket' | 'leaky-bucket''sliding-window'限流算法
storeStore | 'memory' | 'redis://...''memory'存储后端;Redis 可传入连接字符串或 new RedisStore({ client }),原子后端可传入 new CacheHubStore({ client })
keyGeneratorfunction按 IP生成限流键;预定义生成器通过 keyGenerators.* 传入
skipfunction() => false返回 true 时跳过限流
handlerfunction | nullnull超限后的自定义响应处理器
headersbooleantrue是否写入 X-RateLimit-* 响应头
perRouteobject | nullnull按路由覆盖全局配置
skipSuccessfulRequestsbooleanfalse成功响应完成后回滚本次计数
skipFailedRequestsbooleanfalse失败响应完成后回滚本次计数
capacitynumbermax令牌桶/漏桶容量
refillRatenumbercapacity令牌桶在每个 windowMs 内补充的令牌数
leakRatenumbercapacity漏桶在每个 windowMs 内漏出的请求数

Store 接口速查

自定义 Store 至少需要实现 incrementgetsetresetdecrement 用于固定窗口回滚,resetAll 用于全量清理。若实现 checkFixedWindowcheckSlidingWindowcheckTokenBucketcheckLeakyBucket 等快路径,算法层会优先使用它们。

interface Store {
  get(key: string): Promise<any>;
  set(key: string, value: any, ttl?: number): Promise<void>;
  increment(key: string, options?: any): Promise<{ count: number; resetTime?: number }>;
  decrement?(key: string): Promise<void>;
  checkFixedWindow?(key: string, options?: any): Promise<any>;
  checkSlidingWindow?(key: string, options?: any): Promise<any>;
  rollbackSlidingWindow?(key: string, rollbackData?: any): Promise<void>;
  checkTokenBucket?(key: string, options?: any): Promise<any>;
  rollbackTokenBucket?(key: string, rollbackData?: any): Promise<void>;
  checkLeakyBucket?(key: string, options?: any): Promise<any>;
  rollbackLeakyBucket?(key: string, rollbackData?: any): Promise<void>;
  reset(key: string): Promise<void>;
  resetAll?(): Promise<void>;
  close?(): Promise<void>;
}

响应头

当设置 headers: true 时,会添加以下响应头:

  • X-RateLimit-Limit - 允许的最大请求数
  • X-RateLimit-Remaining - 当前窗口剩余请求数
  • X-RateLimit-Reset - 速率限制重置的时间(Unix 时间戳)
  • Retry-After - 重试前等待的秒数(仅在速率受限时)

导出

RateLimiter

主类,用于创建限流器实例。

const { RateLimiter } = require('flex-rate-limit');

RedisStore

Redis 存储后端。

const { RedisStore } = require('flex-rate-limit');

new RedisStore({ client }) 默认不关闭外部 Redis client;设置 ownsClient: true 后,await store.close()await limiter.close() 会关闭该 client。

MemoryStore

内存存储后端(通常不需要直接使用)。

const { MemoryStore } = require('flex-rate-limit');

CacheHubStore

基于 cache-hub@2.2.4 的原子状态后端。可使用内存模式,也可传入 Redis client 使用 Redis Lua 原子路径。

const { CacheHubStore } = require('flex-rate-limit');

预定义键生成器

预定义的键生成器对象。

const { keyGenerators } = require('flex-rate-limit');

// 可用的生成器:
// - keyGenerators.ip
// - keyGenerators.userId
// - keyGenerators.routeAndIp
// - keyGenerators.apiEndpoint
// - keyGenerators.userAndRoute

错误处理

常见错误

try {
  const result = await limiter.check('user-123');
} catch (error) {
  if (error.message.includes('windowMs')) {
    // windowMs 配置错误
  } else if (error.message.includes('max')) {
    // max 配置错误
  } else if (error.message.includes('algorithm')) {
    // algorithm 配置错误
  } else if (error.message.includes('键')) {
    // 键为空或非法
  } else {
    // 其他错误
  }
}

示例代码

基本使用

const { RateLimiter } = require('flex-rate-limit');

const limiter = new RateLimiter({
  windowMs: 60000,
  max: 10,
});

const result = await limiter.check('user-123');
if (result.allowed) {
  console.log('请求被允许');
} else {
  console.log('超过限制,请等待', result.retryAfter, 'ms');
}

中间件使用

const express = require('express');
const { RateLimiter } = require('flex-rate-limit');

const app = express();
const limiter = new RateLimiter({
  windowMs: 60000,
  max: 100,
});

// 全局应用
app.use(limiter.middleware());

// 或特定路由
app.get('/api/data', limiter.middleware(), (req, res) => {
  res.json({ data: 'success' });
});

Redis 使用

const { RateLimiter, RedisStore } = require('flex-rate-limit');
const Redis = require('ioredis');

const redis = new Redis('redis://localhost:6379');

const limiter = new RateLimiter({
  windowMs: 60000,
  max: 100,
  store: new RedisStore({
    client: redis,
    prefix: 'rl:',
  }),
});

// 关闭外部 redis client 仍由调用方负责:
await redis.quit();

CacheHubStore 使用

const Redis = require('ioredis');
const { RateLimiter, CacheHubStore } = require('flex-rate-limit');

const redis = new Redis('redis://localhost:6379');

const limiter = new RateLimiter({
  algorithm: 'sliding-window',
  windowMs: 60000,
  max: 100,
  store: new CacheHubStore({
    client: redis,
    prefix: 'rl:',
  }),
});

await limiter.close();

📚 相关文档

使用指南

返回

动态限制

const limiter = new RateLimiter({
  windowMs: 60000,
  max: async (req) => {
    const user = await getUser(req.user.id);
    return user.isPremium ? 1000 : 100;
  },
});

自定义处理

const limiter = new RateLimiter({
  windowMs: 60000,
  max: 100,
  handler: (req, res) => {
    res.status(429).json({
      error: '请求过于频繁',
    });
  },
});