MCPcopy
hub / github.com/express-rate-limit/express-rate-limit / rateLimit

Function rateLimit

source/rate-limit.ts:345–582  ·  view source on GitHub ↗
(
	passedOptions?: Partial<Options>,
)

Source from the content-addressed store, hash-verified

343 * @public
344 */
345const rateLimit = (
346 passedOptions?: Partial<Options>,
347): RateLimitRequestHandler => {
348 // Parse the options and add the default values for unspecified options
349 const config = parseOptions(passedOptions ?? {})
350 const options = getOptionsFromConfig(config)
351
352 // The limiter shouldn't be created in response to a request (usually)
353 config.validations.creationStack(config.store)
354 // The store instance shouldn't be shared across multiple limiters
355 config.validations.unsharedStore(config.store)
356
357 // Call the `init` method on the store, if it exists
358 if (typeof config.store.init === 'function') {
359 // If store.init() throws or rejects, we'll catch and log it
360 // Use .catch() rather than await, because we need to return synchronously
361 try {
362 const storeInit = config.store.init(options)
363 if (storeInit instanceof Promise) {
364 storeInit.catch((error) =>
365 config.logger.error(
366 error,
367 'express-rate-limit: async error during store initialization.',
368 ),
369 )
370 }
371 } catch (error) {
372 config.logger.error(
373 error,
374 'express-rate-limit: error during store initialization.',
375 )
376 }
377 }
378
379 // Then return the actual middleware
380 const middleware = handleAsyncErrors(
381 async (request: Request, response: Response, next: NextFunction) => {
382 // Attach event listeners immediately — before ANY async work — so events
383 // that fire during skip/key/increment awaits are never missed.
384 const closePromise =
385 config.skipFailedRequests &&
386 new Promise<void>((resolve) => response.once('close', resolve))
387
388 const finishPromise =
389 (config.skipFailedRequests || config.skipSuccessfulRequests) &&
390 new Promise<void>((resolve) => response.once('finish', resolve))
391
392 const errorPromise =
393 config.skipFailedRequests &&
394 new Promise<void>((resolve) => response.once('error', resolve))
395
396 // First check if we should skip the request
397 const skip = await config.skip(request, response)
398 if (skip) {
399 next()
400 return
401 }
402

Callers 15

middleware-test.tsFile · 0.85
headers-test.tsFile · 0.85
options-test.tsFile · 0.85
mongo-store.tsFile · 0.85
redis-store.tsFile · 0.85
memcached-store.tsFile · 0.85
precise-store.tsFile · 0.85
app.tsFile · 0.85
app.jsFile · 0.85
app.tsFile · 0.85
app.jsFile · 0.85
app.tsFile · 0.85

Calls 11

parseOptionsFunction · 0.85
getOptionsFromConfigFunction · 0.85
handleAsyncErrorsFunction · 0.85
setLegacyHeadersFunction · 0.85
setDraft6HeadersFunction · 0.85
setDraft7HeadersFunction · 0.85
setDraft8HeadersFunction · 0.85
decrementKeyFunction · 0.85
setRetryAfterHeaderFunction · 0.85
initMethod · 0.45
incrementMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…