@@ -45,6 +45,7 @@ const slidingWindowRateLimit = async (
4545 c : Context < { Bindings : Bindings ; Variables : Variables } > ,
4646 apiKeyHash : string ,
4747 now : number ,
48+ rateLimit : number ,
4849) : Promise < SlidingWindowResult > => {
4950 const kv = c . env . RATE_LIMITS ;
5051 if ( ! kv ) {
@@ -66,7 +67,7 @@ const slidingWindowRateLimit = async (
6667 state . timestamps = state . timestamps . filter ( ( t ) => t > cutoff ) ;
6768 const count = state . timestamps . length ;
6869
69- if ( count >= RATE_LIMIT ) {
70+ if ( count >= rateLimit ) {
7071 // Rate limit exceeded — calculate retry-after based on oldest request
7172 const oldestTimestamp = state . timestamps [ 0 ] ;
7273 const retryAfter = Math . ceil ( ( oldestTimestamp + WINDOW_MS - now ) / 1000 ) ;
@@ -110,6 +111,7 @@ const fixedWindowRateLimit = async (
110111 c : Context < { Bindings : Bindings ; Variables : Variables } > ,
111112 apiKeyHash : string ,
112113 now : number ,
114+ rateLimit : number ,
113115) : Promise < FixedWindowResult > => {
114116 const db = c . get ( "db" ) ;
115117
@@ -164,7 +166,7 @@ const fixedWindowRateLimit = async (
164166 }
165167
166168 return {
167- allowed : currentCount <= RATE_LIMIT ,
169+ allowed : currentCount <= rateLimit ,
168170 count : currentCount ,
169171 windowEnd,
170172 } ;
@@ -182,6 +184,8 @@ export const rateLimitMiddleware = createMiddleware<{
182184 const apiKeyHash = c . get ( "apiKeyHash" ) ;
183185
184186 const now = Date . now ( ) ;
187+ const configuredRateLimit = Number ( ( c . env as { RATE_LIMIT_MAX ?: string } ) . RATE_LIMIT_MAX ) ;
188+ const rateLimit = Number . isFinite ( configuredRateLimit ) ? configuredRateLimit : RATE_LIMIT ;
185189 // Feature flag: set USE_SLIDING_WINDOW environment variable to "true" to enable
186190 const useSlidingWindow = ( c . env as { USE_SLIDING_WINDOW ?: string } ) . USE_SLIDING_WINDOW === "true" ;
187191
@@ -194,7 +198,7 @@ export const rateLimitMiddleware = createMiddleware<{
194198
195199 if ( useSlidingWindow && c . env . RATE_LIMITS ) {
196200 // Use sliding window with KV
197- const kvResult = await slidingWindowRateLimit ( c , apiKeyHash , now ) ;
201+ const kvResult = await slidingWindowRateLimit ( c , apiKeyHash , now , rateLimit ) ;
198202 if ( kvResult ) {
199203 result = {
200204 allowed : kvResult . allowed ,
@@ -203,7 +207,7 @@ export const rateLimitMiddleware = createMiddleware<{
203207 } ;
204208 } else {
205209 // KV fallback — use fixed window
206- const fixedResult = await fixedWindowRateLimit ( c , apiKeyHash , now ) ;
210+ const fixedResult = await fixedWindowRateLimit ( c , apiKeyHash , now , rateLimit ) ;
207211 result = {
208212 allowed : fixedResult . allowed ,
209213 count : fixedResult . count ,
@@ -212,7 +216,7 @@ export const rateLimitMiddleware = createMiddleware<{
212216 }
213217 } else {
214218 // Use fixed window with D1
215- const fixedResult = await fixedWindowRateLimit ( c , apiKeyHash , now ) ;
219+ const fixedResult = await fixedWindowRateLimit ( c , apiKeyHash , now , rateLimit ) ;
216220 result = {
217221 allowed : fixedResult . allowed ,
218222 count : fixedResult . count ,
@@ -221,7 +225,7 @@ export const rateLimitMiddleware = createMiddleware<{
221225 }
222226
223227 const { allowed, count, retryAfter, windowEnd } = result ;
224- const remaining = Math . max ( 0 , RATE_LIMIT - count ) ;
228+ const remaining = Math . max ( 0 , rateLimit - count ) ;
225229
226230 // Calculate retry-after and reset time
227231 let retryAfterSeconds : number ;
@@ -242,7 +246,7 @@ export const rateLimitMiddleware = createMiddleware<{
242246 }
243247
244248 // Always attach rate limit headers on every response.
245- c . header ( "X-RateLimit-Limit" , String ( RATE_LIMIT ) ) ;
249+ c . header ( "X-RateLimit-Limit" , String ( rateLimit ) ) ;
246250 c . header ( "X-RateLimit-Remaining" , String ( remaining ) ) ;
247251 c . header ( "X-RateLimit-Reset" , String ( resetSeconds ) ) ; // Unix seconds
248252
@@ -252,7 +256,7 @@ export const rateLimitMiddleware = createMiddleware<{
252256 {
253257 error : {
254258 code : "RATE_LIMITED" ,
255- message : `Rate limit exceeded. Maximum ${ RATE_LIMIT } requests per minute. Retry after ${ retryAfterSeconds } seconds.` ,
259+ message : `Rate limit exceeded. Maximum ${ rateLimit } requests per minute. Retry after ${ retryAfterSeconds } seconds.` ,
256260 } ,
257261 } ,
258262 429 ,
0 commit comments