### Custom Store Implementation Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md An example of how to implement a custom store by extending the `Store` interface. This snippet shows the required methods for increment, decrement, and resetKey. ```typescript class CustomStore implements Store { async increment(key: string): Promise { // Implementation return { totalHits: 1, resetTime: new Date() }; } async decrement(key: string): Promise { // Implementation } async resetKey(key: string): Promise { // Implementation } } ``` -------------------------------- ### ClientRateLimitInfo Example Usage Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Demonstrates how to retrieve and use ClientRateLimitInfo from a Store implementation. This shows accessing the total hits and reset time. ```typescript const info = await store.increment("user-123"); console.log(info.totalHits); // 5 console.log(info.resetTime); // Date object or undefined ``` -------------------------------- ### Install hono-rate-limiter Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/README.md Install the hono-rate-limiter package using npm. Peer dependencies include hono and optionally unstorage. ```bash npm install hono-rate-limiter ``` -------------------------------- ### UnstorageStore Constructor and Middleware Setup Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Demonstrates how to initialize Unstorage and use it with the hono-rate-limiter middleware. Ensure Unstorage is imported and created before instantiating UnstorageStore. ```typescript import { createStorage } from "unstorage"; import { UnstorageStore, rateLimiter } from "hono-rate-limiter"; const storage = createStorage(); const store = new UnstorageStore({ storage: storage, prefix: "rate-limit:", }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, }) ); ``` -------------------------------- ### Minimal Rate Limiter Setup Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Use this snippet for a basic rate limiter configuration. It relies on the default in-memory store. ```typescript app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", }) ); ``` -------------------------------- ### Configuring MemoryStore with Hono Middleware Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md This example demonstrates how to integrate the MemoryStore with the `hono-rate-limiter` middleware. It shows setting up the store, defining a key generator, and specifying the rate limiting window and limit. ```typescript import { Hono } from "hono"; import { MemoryStore, rateLimiter } from "hono-rate-limiter"; const app = new Hono(); const store = new MemoryStore(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 15 * 60 * 1000, // 15 minutes limit: 100, }) ); app.get("/api/data", (c) => { const info = c.get("rateLimit"); return c.json({ data: "...", remaining: info.remaining, }); }); // Shutdown handling process.on("SIGTERM", () => { store.shutdown(); }); ``` -------------------------------- ### Full Example with Error Handling and Rate Limit Info Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/webSocketLimiter.md A comprehensive example demonstrating WebSocket rate limiting with custom error handling, a dynamic key generator, and access to rate limit information (remaining requests) within the message handler. It also includes `skipFailedRequests` and a custom `handler`. ```typescript const wsLimiter = webSocketLimiter({ keyGenerator: (c) => { return c.req.header("user-id") || c.req.header("x-forwarded-for") || "unknown"; }, limit: 20, windowMs: 60 * 1000, skipFailedRequests: true, message: "Too many messages, please slow down", handler: (event, ws, options) => { ws.close(options.statusCode, options.message); }, }); app.get("/ws", wsLimiter((c) => ({ onMessage: async (event, ws) => { try { const data = JSON.parse(event.data); // Access rate limit info const info = c.get("rateLimit"); if (info.remaining < 5) { ws.send(JSON.stringify({ warning: "Approaching rate limit", remaining: info.remaining, })); } // Process message const response = await processMessage(data); ws.send(JSON.stringify(response)); } catch (error) { console.error("Error processing message:", error); throw error; } }, onError: (event, ws) => { console.error("WebSocket error:", event); }, onClose: (event, ws) => { console.log("Connection closed"); }, }))); ``` -------------------------------- ### Clone the Repository Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/CONTRIBUTING.md Clone your forked repository locally to start contributing. Ensure you replace `` with your actual GitHub username. ```bash git clone https://github.com//hono-rate-limiter.git cd hono-rate-limiter ``` -------------------------------- ### WSRateLimitExceededEventHandler Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Provides an example implementation for the WebSocket rate limit exceeded event handler. This handler logs a message and closes the WebSocket connection with a specified status code and message. ```typescript const handler: WSRateLimitExceededEventHandler = (event, ws, options) => { console.log("Rate limit exceeded"); ws.close(options.statusCode, options.message); }; ``` -------------------------------- ### KeyGeneratorType Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md An example demonstrating the usage of KeyGeneratorType. This specific implementation generates a client identifier by extracting the 'x-forwarded-for' header or defaulting to 'unknown'. ```typescript const keyGen: KeyGeneratorType = { keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", }; ``` -------------------------------- ### RateLimitExceededEventHandler Example Implementation Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Provides an example of implementing a custom rate limit exceeded event handler. This handler customizes the status code and response message based on the middleware options. ```typescript const customHandler: RateLimitExceededEventHandler = async (c, next, options) => { c.status(options.statusCode); const message = typeof options.message === "function" ? await options.message(c) : options.message; if (typeof message === "string") { return c.text(message); } return c.json(message); }; app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", handler: customHandler, }) ); ``` -------------------------------- ### UnstorageStore ResetKey Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Demonstrates how to completely remove a client's hit counter from storage using resetKey. ```typescript const store = new UnstorageStore({ storage }); const rateLimitStore = c.get("rateLimitStore"); await rateLimitStore.resetKey("user-123"); ``` -------------------------------- ### Accessing Types Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Example of importing various type definitions provided by the library. ```typescript import type { Store, RateLimitInfo, ClientRateLimitInfo, HonoConfigProps, // ... etc } from "hono-rate-limiter"; ``` -------------------------------- ### UnstorageStore Increment Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Demonstrates how to increment a client's hit counter. Shows initial increments and how the counter resets after the window expires. ```typescript const store = new UnstorageStore({ storage }); store.init({ windowMs: 60 * 1000 } as any); const info1 = await store.increment("user-123"); console.log(info1.totalHits); // 1 const info2 = await store.increment("user-123"); console.log(info2.totalHits); // 2 console.log(info2.resetTime); // Same as info1.resetTime // After window expires, next increment resets // (in real scenario, wait 60 seconds) const info3 = await store.increment("user-123"); console.log(info3.totalHits); // 1 (reset) ``` -------------------------------- ### RedisStore with redis-py Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Configure RedisStore using the standard redis-py package. Ensure the Redis client is connected before passing it to the store. This example sets a limit of 1000 requests per hour. ```typescript import { RedisStore, rateLimiter } from "hono-rate-limiter"; import { createClient } from "redis"; const redisClient = createClient({ url: "redis://localhost:6379", }); await redisClient.connect(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: new RedisStore({ client: redisClient, prefix: "api:", }), limit: 1000, windowMs: 60 * 60 * 1000, // 1 hour }) ); ``` -------------------------------- ### Basic Rate Limiter Usage with MemoryStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/rateLimiter.md Demonstrates the fundamental setup of the rate limiter middleware using the default MemoryStore. It configures a limit of 100 requests per 15 minutes and shows how to access the rate limit information within a Hono route handler. ```typescript import { Hono } from "hono"; import { rateLimiter } from "hono-rate-limiter"; const app = new Hono(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", limit: 100, windowMs: 15 * 60 * 1000, // 15 minutes }) ); app.get("/", (c) => { const info = c.get("rateLimit"); return c.json({ message: "Hello", rateLimit: info, }); }); ``` -------------------------------- ### RateLimitInfo Example Usage in Hono Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Shows how to access and utilize RateLimitInfo from the Hono context within a route handler. It demonstrates extracting rate limit details to include in a JSON response. ```typescript app.get("/api/data", (c) => { const info = c.get("rateLimit") as RateLimitInfo; return c.json({ data: "...", rateLimit: { limit: info.limit, used: info.used, remaining: info.remaining, resetsAt: info.resetTime?.toISOString(), }, }); }); ``` -------------------------------- ### Basic WebSocket Rate Limiting Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/README.md Set up WebSocket rate limiting with webSocketLimiter. This example limits connections to 10 per minute per IP address. ```typescript import { webSocketLimiter } from "hono-rate-limiter"; const wsLimiter = webSocketLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", limit: 10, windowMs: 60 * 1000, }); app.get("/ws", wsLimiter((c) => ({ onMessage: (event, ws) => { ws.send("Echo: " + event.data); }, }))); ``` -------------------------------- ### Invalid Store Error Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/README.md Illustrates an error message when the provided storage implementation is invalid, specifically missing the required 'increment' method. ```plaintext Error: The store is not correctly implemented! ``` -------------------------------- ### Multi-Environment Configuration with Environment Variable Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/configuration.md Dynamically configure the rate limiter based on the `ENVIRONMENT` variable, providing distinct settings for development, staging, and production. This example includes `skipFailedRequests` and a Redis store for production. ```typescript const getConfig = () => { const base = { keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", skipFailedRequests: true, }; switch (process.env.ENVIRONMENT) { case "development": return { ...base, limit: 1000, windowMs: 60 * 60 * 1000 }; case "staging": return { ...base, limit: 500, windowMs: 15 * 60 * 1000 }; case "production": return { ...base, limit: 100, windowMs: 15 * 60 * 1000, store: new RedisStore({ client: redisClient }), }; } }; app.use(rateLimiter(getConfig())); ``` -------------------------------- ### Promisify Utility Type Example Usage Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Illustrates the use of the Promisify type for synchronous and asynchronous key generators. It shows how a function can return either a direct value or a Promise. ```typescript // Synchronous key generator const syncGen: Promisify = "fixed-key"; // Asynchronous key generator const asyncGen: Promisify = Promise.resolve("dynamic-key"); // Function that returns Promisify function keyGenerator(c: Context): Promisify { if (cached) return cached; return fetchFromDatabase(); } ``` -------------------------------- ### UnstorageStore Decrement Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Illustrates decrementing a client's hit counter. Shows successful decrements and how it behaves when the counter is already zero or outside the active window. ```typescript const store = new UnstorageStore({ storage }); await store.increment("user-123"); console.log((await store.get("user-123")).totalHits); // 1 await store.decrement("user-123"); console.log((await store.get("user-123")).totalHits); // 0 await store.decrement("user-123"); // Outside window or already 0 console.log((await store.get("user-123")).totalHits); // 0 (no change) ``` -------------------------------- ### Retrieving Client Rate Limit Information Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Demonstrates how to fetch the current hit count and reset time for a specific client identifier using the get method. Handles different storage value types and returns undefined if no data is found. ```typescript const store = new UnstorageStore({ storage }); const info = await store.get("192.168.1.1"); if (info) { console.log("Hits:", info.totalHits); console.log("Resets at:", info.resetTime); } ``` -------------------------------- ### Get Client Rate Limit Info from RedisStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Demonstrates retrieving the current hit count and reset time for a client identifier from Redis without altering the stored values. Returns undefined if the client key does not exist. ```typescript const store = new RedisStore({ client: redisClient }); const info = await store.get("192.168.1.1"); if (info) { console.log("Total hits:", info.totalHits); console.log("Resets at:", info.resetTime); } ``` -------------------------------- ### Initialize RedisStore with Custom Options Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Demonstrates how to create a RedisStore instance with a custom Redis client, key prefix, and reset expiry behavior. Ensure your Redis client is connected before passing it. ```typescript import { RedisStore, rateLimiter } from "hono-rate-limiter"; import { createClient } from "redis"; const redisClient = createClient(); await redisClient.connect(); const store = new RedisStore({ client: redisClient, prefix: "api_rl:", resetExpiryOnChange: false, }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, }) ); ``` -------------------------------- ### MemoryStore Constructor Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md Initializes a new MemoryStore instance. No parameters are required for the constructor. ```APIDOC ## MemoryStore Constructor ### Description Initializes a new MemoryStore instance. No parameters are required for the constructor. ### Constructor ```typescript constructor() ``` ### Example ```typescript import { MemoryStore } from "hono-rate-limiter"; const store = new MemoryStore(); ``` ``` -------------------------------- ### Dynamic Limit per User for WebSocket Rate Limiting Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/webSocketLimiter.md Implements dynamic rate limiting based on a 'user-id' header. Premium users (with a 'user-id') get a higher limit (100), while anonymous users get a lower limit (10). ```typescript const wsLimiter = webSocketLimiter({ keyGenerator: (c) => c.req.header("user-id") || "anonymous", limit: async (c) => { const userId = c.req.header("user-id"); return userId ? 100 : 10; // Premium vs anonymous limits }, }); ``` -------------------------------- ### UnstorageStore.init Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Initializes the store with configuration options. This method is automatically called by the middleware. ```APIDOC ## Method init ### Description Initializes the store with configuration options. Must be called before use (automatically called by the middleware). ### Parameters - **options** (`HonoConfigType`) - Configuration object containing `windowMs` and other settings. ### Behavior - Stores the `windowMs` value for later use in expiration calculations - Does not set up any timers (unlike MemoryStore) ### Example ```typescript const store = new UnstorageStore({ storage }); const middleware = rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 60 * 1000, }); // init() is called automatically by the middleware ``` ``` -------------------------------- ### RedisStore Methods Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Provides methods for initializing the store, managing keys, and retrieving rate limit information. ```APIDOC ## init(options: RateLimitConfiguration): void ### Description Initializes the store with configuration options. Must be called before use (automatically called by the middleware). ### Parameters #### options - **options** (RateLimitConfiguration) - Configuration object containing `windowMs`. ### Behavior - Stores the `windowMs` value - The Lua scripts are already being loaded in the constructor (asynchronously) ### Example ```typescript const store = new RedisStore({ client: redisClient }); const middleware = rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 60 * 1000, }); // init() is called automatically ``` ## prefixKey(key: string): string ### Description Prepends the configured prefix to a key. ### Parameters #### key - **key** (string) - The client identifier. ### Return Type Returns `string`: The prefixed key. ### Behavior - Concatenates `this.prefix + key` - Used internally before all Redis operations ### Example ```typescript const store = new RedisStore({ client: redisClient, prefix: "rl:", }); const prefixed = store.prefixKey("user-123"); console.log(prefixed); // "rl:user-123" ``` ## get(key: string): Promise ### Description Retrieves the hit count and reset time for a client without modifying it. ### Parameters #### key - **key** (string) - Unique identifier for the client. ### Return Type Returns `Promise`: ```typescript type ClientRateLimitInfo = { totalHits: number; resetTime: Date; }; ``` ### Behavior 1. Waits for the `getScriptSha` promise to resolve 2. Executes Redis `EVALSHA` with the get Lua script 3. Passes the prefixed key to the script 4. The script returns `[totalHits, timeToExpireMs]` 5. Parses the response via `parseScriptResponse()` 6. Returns `undefined` if the key doesn't exist ### Example ```typescript const store = new RedisStore({ client: redisClient }); const info = await store.get("192.168.1.1"); if (info) { console.log("Total hits:", info.totalHits); console.log("Resets at:", info.resetTime); } ``` ``` -------------------------------- ### UnstorageStore Initialization with Middleware Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Shows how to initialize UnstorageStore and integrate it with the rateLimiter middleware, where the store's init method is automatically called. ```typescript const store = new UnstorageStore({ storage }); const middleware = rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 60 * 1000, }); // init() is called automatically by the middleware ``` -------------------------------- ### Initialize MemoryStore with Custom Window Time Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md Demonstrates initializing the MemoryStore and the rateLimiter middleware with a custom window duration (1 minute). The init() method is called automatically by the middleware. ```typescript const store = new MemoryStore(); const middleware = rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 60 * 1000, // 1 minute }); // init() is called automatically by the middleware ``` -------------------------------- ### Redis Script Error Example Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/README.md Shows a potential error that can occur during Redis operations, indicating an unexpected response from the Redis client. ```plaintext TypeError: unexpected reply from redis client ``` -------------------------------- ### Accessing RedisStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Demonstrates how to import the RedisStore, either directly or from the stores export. ```typescript import { RedisStore } from "hono-rate-limiter"; // or import { RedisStore } from "hono-rate-limiter/stores"; ``` -------------------------------- ### MemoryStore.init Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md Initializes the MemoryStore with configuration options, including the time window for rate limiting. This method is typically called automatically by the rate limiter middleware. ```APIDOC ## MemoryStore.init ### Description Initializes the store with configuration options. Must be called before use (automatically called by the middleware). ### Method Signature ```typescript init(options: HonoConfigType | WSConfigType): void ``` ### Parameters #### Parameters - **options** (HonoConfigType \| WSConfigType) - Required - Configuration object containing `windowMs` and other rate limiter settings. ### Behavior - Stores the `windowMs` value - Sets up an interval timer that runs every `windowMs` milliseconds - The timer moves all clients in `current` to `previous` and clears the old `previous` map - Makes the interval timer non-blocking (calls `unref()` on Node.js timers) - If `init()` is called multiple times, clears any existing interval first ### Example ```typescript const store = new MemoryStore(); const middleware = rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 60 * 1000, // 1 minute }); // init() is called automatically by the middleware ``` ``` -------------------------------- ### Initialize RedisStore and Middleware Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Shows how to initialize the RedisStore and then use it within the Hono rateLimiter middleware, specifying the window duration. The store's init method is called automatically by the middleware. ```typescript const store = new RedisStore({ client: redisClient }); const middleware = rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, windowMs: 60 * 1000, }); // init() is called automatically ``` -------------------------------- ### Accessing UnstorageStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Demonstrates how to import the UnstorageStore, either directly or from the stores export. ```typescript import { UnstorageStore } from "hono-rate-limiter"; // or import { UnstorageStore } from "hono-rate-limiter/stores"; ``` -------------------------------- ### Skipping Rate Limiter for Specific Routes Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/rateLimiter.md Configures the rate limiter to bypass checks for routes starting with '/health'. This is useful for health check endpoints that should not be rate-limited. ```typescript app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", skip: (c) => { return c.req.path.startsWith("/health"); }, }) ); ``` -------------------------------- ### Initialize MemoryStore and Rate Limiter Middleware Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md Instantiate MemoryStore and use it with the rateLimiter middleware. The keyGenerator extracts the client's IP address for tracking. ```typescript import { MemoryStore, rateLimiter } from "hono-rate-limiter"; const store = new MemoryStore(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, }) ); ``` -------------------------------- ### Store Interface Definition Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Defines the contract that all hit counter stores must implement. This includes methods for initializing, getting, incrementing, decrementing, resetting counts, and shutting down the store. ```typescript type Store = { init?: (options: HonoConfigType) => void; get?: (key: string) => Promisify; increment: (key: string) => Promisify; decrement: (key: string) => Promisify; resetKey: (key: string) => Promisify; resetAll?: () => Promisify; shutdown?: () => Promisify; localKeys?: boolean; prefix?: string; }; ``` -------------------------------- ### Reset Client Counter in Redis Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Completely removes a client's hit counter from Redis. Subsequent requests from this client will start a new counter. This is useful for manual resets. ```typescript const store = new RedisStore({ client: redisClient }); const rateLimitStore = c.get("rateLimitStore"); await rateLimitStore.resetKey("user-123"); ``` -------------------------------- ### Accessing MemoryStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Demonstrates how to import the MemoryStore, either directly or from the stores export. ```typescript import { MemoryStore } from "hono-rate-limiter"; // or import { MemoryStore } from "hono-rate-limiter/stores"; ``` -------------------------------- ### UnstorageStore Constructor Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Initializes a new UnstorageStore instance. It requires an Unstorage instance and optionally accepts a prefix for keys. ```APIDOC ## Constructor UnstorageStore ### Description Initializes a new UnstorageStore instance. It requires an Unstorage instance and optionally accepts a prefix for keys. ### Parameters - **options.storage** (`UnstorageInstance`) - Required - An Unstorage instance that implements `get`, `set`, and `remove` methods. - **options.prefix** (`string`) - Optional - String prepended to all keys. Useful for namespacing rate limit data. Defaults to "hrl:". ### Example ```typescript import { createStorage } from "unstorage"; import { UnstorageStore, rateLimiter } from "hono-rate-limiter"; const storage = createStorage(); const store = new UnstorageStore({ storage: storage, prefix: "rate-limit:", }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, }) ); ``` ``` -------------------------------- ### RedisStore Constructor Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Initializes a new RedisStore instance. It requires a Redis client and allows configuration of key prefixes and expiry behavior. ```APIDOC ## new RedisStore(options: Options) ### Description Initializes a new RedisStore instance. It requires a Redis client and allows configuration of key prefixes and expiry behavior. ### Parameters #### Options - **client** (RedisClient) - Required - A Redis client that implements the required methods. Supports any Redis client library (e.g., `@upstash/redis`, `redis`, `ioredis`). - **prefix** (string) - Optional - String prepended to all Redis keys for namespacing. Defaults to `"hrl:"`. - **resetExpiryOnChange** (boolean) - Optional - If `true`, resets the key's TTL every time the counter is incremented. If `false`, TTL is set once when the key is created. Defaults to `false`. ### Example ```typescript import { RedisStore, rateLimiter } from "hono-rate-limiter"; import { createClient } from "redis"; const redisClient = createClient(); await redisClient.connect(); const store = new RedisStore({ client: redisClient, prefix: "api_rl:", resetExpiryOnChange: false, }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: store, }) ); ``` ``` -------------------------------- ### Skipping Health Checks and Metrics Requests Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/configuration.md Configures rate limiting to skip requests to '/health', '/metrics', and any path starting with '/public'. It uses the 'x-forwarded-for' header or 'unknown' as the key generator. ```typescript app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", skip: (c) => { return ( c.req.path === "/health" || c.req.path === "/metrics" || c.req.path.startsWith("/public") ); }, }) ); ``` -------------------------------- ### Resetting a Specific Client Key in MemoryStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md This method completely removes a client's hit counter from the store. After resetting, the client's next request will start with a fresh counter. ```typescript const store = new MemoryStore(); const rateLimitStore = c.get("rateLimitStore"); // Reset a specific client await rateLimitStore.resetKey("user-123"); // Client's next request will start fresh ``` -------------------------------- ### Get Client Rate Limit Information Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md Retrieve the current hit count and reset time for a given client key without modifying the store. Checks both current and previous client data. ```typescript const store = new MemoryStore(); const info = store.get("192.168.1.1"); if (info) { console.log("Client has", info.totalHits, "hits"); console.log("Resets at", info.resetTime); } ``` -------------------------------- ### Skip Successful Messages, Count Only Errors in WebSocket Rate Limiting Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/webSocketLimiter.md Configures rate limiting to only count failed or errored messages by setting `skipSuccessfulRequests` to true. This example demonstrates counting errors thrown during message processing. ```typescript const wsLimiter = webSocketLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", skipSuccessfulRequests: true, // Only count failed/errored messages limit: 5, }); app.get("/ws", wsLimiter((c) => ({ onMessage: (event, ws) => { try { const data = JSON.parse(event.data); ws.send(JSON.stringify({ success: true, data })); } catch (e) { // This error will be counted throw e; } }, }))); ``` -------------------------------- ### Prefixing Keys with UnstorageStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Illustrates how to use the prefixKey method to prepend a custom namespace to client identifiers, ensuring data isolation within Unstorage. ```typescript const store = new UnstorageStore({ storage, prefix: "rl:", }); const prefixed = store.prefixKey("user-123"); console.log(prefixed); // "rl:user-123" ``` -------------------------------- ### Hono Rate Limiter with Redis Backend (Upstash) Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Sets up the Hono rate limiter middleware with UnstorageStore using the Upstash Redis driver. Requires environment variables for Redis connection details. ```typescript import { UnstorageStore, rateLimiter } from "hono-rate-limiter"; import { createStorage } from "unstorage"; import upstashDriver from "unstorage/drivers/upstash"; const storage = createStorage({ driver: upstashDriver({ url: process.env.UPSTASH_REDIS_REST_URL, token: process.env.UPSTASH_REDIS_REST_TOKEN, }), }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: new UnstorageStore({ storage, prefix: "rate_limit:" }), }) ); ``` -------------------------------- ### Main Entry Point Exports Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Exports from the main entry point of the library, including the rate limiter middleware and WebSocket limiter. ```typescript export { rateLimiter } from "./rateLimiter"; export * from "./stores"; export type * from "./types"; export { webSocketLimiter } from "./websocket"; ``` -------------------------------- ### Development vs. Production Configuration Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/configuration.md Conditionally configure the rate limiter based on the `NODE_ENV` environment variable. Development uses a higher limit and shorter window, while production uses stricter limits and a Redis store. ```typescript const config = process.env.NODE_ENV === "development" ? { keyGenerator: (c) => "dev", limit: 10000, windowMs: 60 * 60 * 1000, } : { keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", limit: 100, windowMs: 15 * 60 * 1000, store: new RedisStore({ client: redisClient }), }; app.use(rateLimiter(config)); ``` -------------------------------- ### Import Statements - Main Middleware and Stores Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Quick reference for importing the main middleware functions and store classes. ```typescript // Main middleware import { rateLimiter, webSocketLimiter } from "hono-rate-limiter"; // Stores import { MemoryStore, RedisStore, UnstorageStore } from "hono-rate-limiter"; ``` -------------------------------- ### Hono Rate Limiter with File System Backend Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Configures the Hono rate limiter middleware using UnstorageStore with a local file system driver. Specifies a key generator, storage instance, request limit, and window duration. ```typescript import { UnstorageStore, rateLimiter } from "hono-rate-limiter"; import { createStorage } from "unstorage"; import fsDriver from "unstorage/drivers/fs"; const storage = createStorage({ driver: fsDriver({ base: "./data" }), }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: new UnstorageStore({ storage, prefix: "api_rl:" }), limit: 100, windowMs: 15 * 60 * 1000, }) ); ``` -------------------------------- ### Prefix Key with RedisStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/redisstore.md Illustrates how the RedisStore class prepends a configured prefix to a given key. This is used internally to namespace keys in Redis. ```typescript const store = new RedisStore({ client: redisClient, prefix: "rl:", }); const prefixed = store.prefixKey("user-123"); console.log(prefixed); // "rl:user-123" ``` -------------------------------- ### Store Classes Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Provides different implementations for storing rate limit information. Users can choose between MemoryStore, RedisStore, and UnstorageStore. ```APIDOC ## Store Implementations ### Description These classes provide the underlying storage mechanism for rate limiting data. You can import and use them directly or via the main export. ### Available Stores - **MemoryStore**: Stores rate limit data in memory. ```typescript import { MemoryStore } from 'hono-rate-limiter' // or import { MemoryStore } from 'hono-rate-limiter/stores' ``` - **RedisStore**: Stores rate limit data using a Redis client. ```typescript import { RedisStore } from 'hono-rate-limiter' // or import { RedisStore } from 'hono-rate-limiter/stores' ``` For Redis-specific types like `RedisClient` and `Options`, refer to [RedisStore](./api-reference/redisstore.md). - **UnstorageStore**: Stores rate limit data using the Unstorage library. ```typescript import { UnstorageStore } from 'hono-rate-limiter' // or import { UnstorageStore } from 'hono-rate-limiter/stores' ``` For Unstorage-specific types like `UnstorageInstance`, refer to [UnstorageStore](./api-reference/unstoragestore.md). ### Usage When configuring `rateLimiter` or `webSocketLimiter`, you can pass an instance of these store classes: ```typescript import { rateLimiter } from 'hono-rate-limiter' import { RedisStore } from 'hono-rate-limiter/stores' const redisStore = new RedisStore({ // Redis client options }) app.use( '/api/*', rateLimiter({ store: redisStore, windowSize: 60000, limit: 100, }) ) ``` ``` -------------------------------- ### Basic In-Memory Unstorage Configuration Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/unstoragestore.md Set up Unstorage for rate limiting using its default in-memory driver. This is suitable for development or single-instance applications. ```typescript import { UnstorageStore, rateLimiter } from "hono-rate-limiter"; import { createStorage } from "unstorage"; // In-memory storage (like MemoryStore but with Unstorage abstraction) const storage = createStorage(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: new UnstorageStore({ storage }), }) ); ``` -------------------------------- ### Unstorage for Flexible Storage Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/configuration.md Integrate Unstorage with a file system driver for flexible and persistent storage of rate limit data. Configure the base directory for storage. ```typescript import { UnstorageStore } from "hono-rate-limiter"; import { createStorage } from "unstorage"; import fsDriver from "unstorage/drivers/fs"; const storage = createStorage({ driver: fsDriver({ base: "./rate-limit-data" }), }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: new UnstorageStore({ storage, prefix: "rl:", }), }) ); ``` -------------------------------- ### MemoryStore.get Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/memorystore.md Retrieves the current rate limit information for a given client key without modifying the store. ```APIDOC ## MemoryStore.get ### Description Retrieves the hit count and reset time for a client without modifying it. ### Method Signature ```typescript get(key: string): ClientRateLimitInfo | undefined ``` ### Parameters #### Parameters - **key** (string) - Required - Unique identifier for the client (returned by `keyGenerator`). ### Return Type Returns `ClientRateLimitInfo | undefined`: ```typescript type ClientRateLimitInfo = { totalHits: number; // Number of hits in current window resetTime?: Date; // Time when counter resets }; ``` Returns `undefined` if the client has no stored data. ### Behavior - Checks `current` map first, then `previous` map - Does not modify any counters - Returns the exact client object (not a copy) ### Example ```typescript const store = new MemoryStore(); const info = store.get("192.168.1.1"); if (info) { console.log("Client has", info.totalHits, "hits"); console.log("Resets at", info.resetTime); } ``` ``` -------------------------------- ### Import Statements - Types Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Quick reference for importing type definitions for rate limiting configurations and information. ```typescript // Types import type { Store, RateLimitInfo, HonoConfigProps, CloudflareConfigProps, WSConfigProps, } from "hono-rate-limiter"; ``` -------------------------------- ### Using Redis Store for WebSocket Rate Limiting Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/webSocketLimiter.md Integrates the WebSocket rate limiter with a Redis store for persistent rate limiting across multiple instances. Requires a `RedisStore` implementation and a Redis client instance (`redisClient`). ```typescript import { RedisStore } from "hono-rate-limiter"; const wsLimiter = webSocketLimiter({ keyGenerator: (c) => c.req.header("user-id") || "anonymous", store: new RedisStore({ client: redisClient, prefix: "ws_rl:", }), limit: 50, windowMs: 60 * 1000, }); app.get("/ws", wsLimiter((c) => ({ onMessage: (event, ws) => { ws.send("OK"); }, }))); ``` -------------------------------- ### Rate Limiter with Unstorage Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/rateLimiter.md Configures the rate limiter to use Unstorage for storing rate limit data, providing flexibility with various storage backends. It sets up the Unstorage instance and specifies a prefix for the rate limit keys. ```typescript import { UnstorageStore } from "hono-rate-limiter"; import { createStorage } from "unstorage"; const storage = createStorage(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store: new UnstorageStore({ storage, prefix: "rate-limit:", }), }) ); ``` -------------------------------- ### Basic WebSocket Rate Limiting Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-reference/webSocketLimiter.md Sets up basic rate limiting for WebSocket connections, limiting to 10 messages per minute per IP address. Requires importing Hono and webSocketLimiter. ```typescript import { Hono } from "hono"; import { webSocketLimiter } from "hono-rate-limiter"; const app = new Hono(); const wsLimiter = webSocketLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", limit: 10, windowMs: 60 * 1000, // 1 minute }); app.get("/ws", wsLimiter((c) => ({ onMessage: (event, ws) => { console.log("Message:", event.data); ws.send("Echo: " + event.data); }, onClose: (event, ws) => { console.log("Closed"); }, }))); ``` -------------------------------- ### Rate Limiter with Custom Redis Store Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Configure the rate limiter to use a custom Redis store for managing rate limiting data across multiple instances. Ensure your Redis client is properly initialized. ```typescript const store = new RedisStore({ client: redisClient }); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", store, }) ); ``` -------------------------------- ### Tiered Rate Limiting Configuration Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/configuration.md Implements tiered rate limiting based on user ID. Anonymous users have a limit of 10 requests per hour, while premium users have 10000 and standard users have 1000. It prioritizes 'user-id' header for key generation. ```typescript app.use( rateLimiter({ keyGenerator: async (c) => { const userId = c.req.header("user-id"); return userId || c.req.header("x-forwarded-for") || "unknown"; }, limit: async (c) => { const userId = c.req.header("user-id"); if (!userId) return 10; // 10 for anonymous const user = await getUser(userId); return user.isPremium ? 10000 : 1000; // Tiered limits }, windowMs: 60 * 60 * 1000, // 1 hour }) ); ``` -------------------------------- ### MemoryStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md In-memory storage implementation for rate limiting. Stores client data in memory. ```APIDOC ## MemoryStore ### Description In-memory storage implementation for rate limiting. Stores client data in memory. ### Signature `class MemoryStore implements Store` ### Constructor `new MemoryStore()` ### Methods - `init(options: HonoConfigType): void` - `get(key: string): ClientRateLimitInfo | undefined` - `increment(key: string): ClientRateLimitInfo` - `decrement(key: string): void` - `resetKey(key: string): void` - `resetAll(): void` - `shutdown(): void` ### Properties - `previous: Map` - `current: Map` - `interval?: any` ``` -------------------------------- ### Hybrid Key Generation Strategy Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/configuration.md Combine user ID and IP address for a more robust key generation strategy. This approach provides defense-in-depth by considering both user identity and network origin. ```typescript keyGenerator: (c) => { const userId = extractUserId(c); const ip = c.req.header("x-forwarded-for") || "unknown"; return userId ? `user_${userId}` : `ip_${ip}`; } ``` -------------------------------- ### Basic HTTP Rate Limiting with Hono Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/README.md Implement HTTP rate limiting using the rateLimiter middleware. It uses a key generator to identify clients by IP address. ```typescript import { Hono } from "hono"; import { rateLimiter } from "hono-rate-limiter"; const app = new Hono(); app.use( rateLimiter({ keyGenerator: (c) => c.req.header("x-forwarded-for") || "unknown", }) ); app.get("/api/data", (c) => { const info = c.get("rateLimit"); return c.json({ data: "...", remaining: info.remaining, }); }); ``` -------------------------------- ### HonoConfigProps Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/types.md Configuration options for Hono-based rate limiting where all fields except `keyGenerator` are optional, utilizing default values for convenience. ```APIDOC ## HonoConfigProps ### Description Configuration options for Hono-based rate limiting where all fields except `keyGenerator` are optional (uses defaults). ### Properties This type is a combination of `KeyGeneratorType` and `Partial`, with `binding` explicitly set to `never` to prevent its use. ``` -------------------------------- ### Store Exports Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Exports for different storage implementations available in the library. ```typescript export * from "./memory"; export * from "./redis"; export * from "./unstorage"; ``` -------------------------------- ### UnstorageStore Source: https://github.com/rhinobase/hono-rate-limiter/blob/main/_autodocs/api-index.md Storage implementation using Unstorage for rate limiting. Persists rate limit data using a provided Unstorage instance. ```APIDOC ## UnstorageStore ### Description Storage implementation using Unstorage for rate limiting. Persists rate limit data using a provided Unstorage instance. ### Signature `class UnstorageStore implements Store` ### Constructor `new UnstorageStore(options: { storage: UnstorageInstance; prefix?: string })` ### Methods - `init(options: HonoConfigType): void` - `prefixKey(key: string): string` - `get(key: string): Promise` - `increment(key: string): Promise` - `decrement(key: string): Promise` - `resetKey(key: string): Promise` ### Properties - `windowMs: number` - `prefix: string` - `storage: UnstorageInstance` ```