Gathering detailed insights and metrics for @kuizto/bite-limiter
Gathering detailed insights and metrics for @kuizto/bite-limiter
Gathering detailed insights and metrics for @kuizto/bite-limiter
Gathering detailed insights and metrics for @kuizto/bite-limiter
npm install @kuizto/bite-limiter
Typescript
Module System
Node Version
NPM Version
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
⚠️ Work in progress, not published yet ⚠️
Lightweight rate limiting for Web APIs — compatible with Node.js, Cloudflare Workers, browsers, etc...
⚠️ Work in progress, not published yet ⚠️
1pnpm add @kuizto/bite-limiter
1import { BiteLimiter } from '@kuizto/bite-limiter'
2
3const ratelimiter = new BiteLimiter({
4 prefix: 'user', // Storage key prefix
5 windowMs: 15 * 60 * 1000, // 15 minutes
6 limit: 100, // Limit to 100 requests per `window` (here, per 15 minutes).
7 // store: ... , // Durable Objects, Workers KV, etc. See below.
8})
9
10const { ok, remaining } = await ratelimiter.check(userId)
11
12if (!ok) {
13 throw new Error('rate limited')
14}
Status | Name | Description | Environment |
---|---|---|---|
⚠️ | RedisStore | Use Redis immediate consistency for rate limiting via REST API, suitable for all distributed environments (Upstash Redis compatible). | All |
⚠️ | DatabaseStore | Use any Database to enforce rate limiting through Hook functions, ideal for distributed systems and adaptable to various databases and ORMs. | All |
⚠️ | CloudflareDurableStore | Use Cloudflare Durable Objects for strong consistency and isolation, ideal for stateful rate limiting at the edge. | CF Workers only |
✅ Ready to use. ⚠️ Work in progress.
1// src/lib/rateLimiter.ts
2const ratelimiter = new BiteLimiter({
3 windowMs: 60 * 1000, // 1 minute
4 limit: 1000, // Limit to 1,000 req per `window`
5 store: new RedisStore('https://redis-endpoint.com')
6})
7
8// src/hooks.server.ts
9export const handle: Handle = async ({ event, resolve }) => {
10 if (event.url.pathname.startsWith('/custom')) {
11 return new Response('custom response')
12 }
13 const limit = ratelimiter.check(userId)
14 if (!limit.ok) error(429);
15 return await resolve(event)
16}
1[[durable_objects.bindings]] 2class_name = "BiteLimiterDurableObject" 3name = "BITE_LIMITER"
1// export durable object for binding with env.BITE_LIMITER 2export { BiteLimiterDurableObject } from '@kuizto/bite-limiter' 3 4// rate limiter using durable object 5const ratelimiter = new BiteLimiter({ 6 limit: 50, // 50 req per sec 7 store: new CloudflareDurableStore(env.BITE_LIMITER) 8}) 9 10// hono middleware 11const rateLimitMiddleware: MiddlewareHandler = async (c, next) => {x 12 const userId = c.req.param('userId') 13 const limit = ratelimiter.check(userId) 14 if (!limit.ok) { 15 return c.text('too many requests', 429) 16 } 17 await next() 18} 19 20// hono router 21app.get("/api/:userId/operation", rateLimitMiddleware, myHandler)
1// schema 2export const RateLimiter = sqliteTable('RateLimiter', { 3 key: text('key').notNull(), 4 timestamp: integer('timestamp').notNull(), 5}, (RateLimiter) => ({ 6 idx_rateLimiterkey: index('idx_rateLimiterkey').on(RateLimiter.key), 7 idx_rateLimiter_timestamp: index('idx_rateLimiter_timestamp').on(RateLimiter.timestamp), 8}))
1// drizzle orm 2const sqlite = new Database('sqlite.db'); 3const db = drizzle(sqlite); 4 5// rate limiter 6const ratelimiter = new BiteLimiter({ 7 limit: 10, // 10 req per sec 8 store: new DatabaseStore({ 9 async insertTimestamp(key, timestamp) { 10 await db.insert(RateLimiter).values({ key, timestamp }) 11 }, 12 async deleteTimestampsBefore(oldestValidTimestamp) { 13 await db.delete(RateLimiter).where(lt(RateLimiter.timestamp, oldestValidTimestamp)) 14 }, 15 async deleteAllTimestampsFor(key) { 16 await db.delete(RateLimiter).where(eq(RateLimiter.key, key)) 17 }, 18 async countValidTimestamps(key, oldestValidTimestamp) { 19 const resp = await db.select({ count: count() }) 20 .from(RateLimiter) 21 .where(and( 22 eq(RateLimiter.key, key), 23 gte(RateLimiter.timestamp, oldestValidTimestamp) 24 )) 25 return resp?.[0]?.count || 0 26 }, 27 }) 28}) 29 30// main handler 31export async function handler(event) { 32 const limit = await ratelimiter.check() 33 34 if (!limit.ok) { 35 return { 36 statusCode: 429, 37 headers: { 'Content-Type': 'application/json' }, 38 body: JSON.stringify(limit), 39 } 40 } 41 42 return { 43 statusCode: 200, 44 headers: { 'Content-Type': 'application/json' }, 45 body: JSON.stringify(limit), 46 } 47}
Contributions and pull requests are welcome!
Open-sourced under the MIT license.
No vulnerabilities found.
No security vulnerabilities found.