@hono-rate-limiter/cloudflare
Version:
Cloudflare stores and helper functions for hono-rate-limiter.
2 lines (1 loc) • 2.56 kB
JavaScript
"use strict";var e=require("cloudflare:workers");const t={totalHits:0};class s extends e.DurableObject{value(){return this.ctx.storage.get("value")}async update(e,s){let a=await this.ctx.storage.get("value")||t;const i=new Date(a.resetTime??Date.now()+s);a={totalHits:a.totalHits+e,resetTime:i};return null==await this.ctx.storage.getAlarm()&&this.ctx.storage.setAlarm(i.getTime()),await this.ctx.storage.put("value",a),a}async reset(){await this.ctx.storage.put("value",t)}async alarm(){await this.reset()}}exports.DurableObjectRateLimiter=s,exports.DurableObjectStore=class{constructor(e){this.namespace=e.namespace,this.prefix=e.prefix??"hrl:"}prefixKey(e){return this.namespace.idFromName(`${this.prefix}${e}`)}init(e){this.windowMs=e.windowMs}async get(e){return this.namespace.get(this.prefixKey(e)).value()}async increment(e){return this.namespace.get(this.prefixKey(e)).update(1,this.windowMs)}async decrement(e){await this.namespace.get(this.prefixKey(e)).update(-1,this.windowMs)}async resetKey(e){await this.namespace.get(this.prefixKey(e)).reset()}},exports.WorkersKVStore=class{constructor(e){this.namespace=e.namespace,this.prefix=e.prefix??"hrl:"}prefixKey(e){return`${this.prefix}${e}`}init(e){this.windowMs=e.windowMs}async get(e){const t=await this.namespace.get(this.prefixKey(e),"json");if(t)return t}async increment(e){let t={totalHits:1,resetTime:new Date(Date.now()+this.windowMs)};const s=await this.get(e);return s&&(t={totalHits:s.totalHits+1,resetTime:s.resetTime?new Date(s.resetTime):t.resetTime}),await this.namespace.put(this.prefixKey(e),JSON.stringify(t),{expiration:t.resetTime.getTime()/1e3}),t}async decrement(e){const t=await this.get(e);t&&t.resetTime&&(t.totalHits-=1,await this.namespace.put(this.prefixKey(e),JSON.stringify(t),{expiration:Math.floor(t.resetTime.getTime()/1e3)}))}async resetKey(e){await this.namespace.delete(this.prefixKey(e))}},exports.cloudflareRateLimiter=function(e){const{message:t="Too many requests, please try again later.",statusCode:s=429,requestPropertyName:a="rateLimit",rateLimitBinding:i,keyGenerator:r,skip:n=(()=>!1),handler:o=(async(e,t,s)=>{e.status(s.statusCode);const a="function"==typeof s.message?await s.message(e):s.message;return"string"==typeof a?e.text(a):e.json(a)})}=e;return async(e,c)=>{let p=i;"function"==typeof p&&(p=p(e));const m={message:t,statusCode:s,requestPropertyName:a,rateLimitBinding:p,keyGenerator:r,skip:n,handler:o};if(await n(e))return void await c();const u=await r(e),{success:h}=await p.limit({key:u});if(e.set(a,h),!h)return o(e,c,m);await c()}};