( passedOptions?: Partial<Options>, )
| 343 | * @public |
| 344 | */ |
| 345 | const 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 |
no test coverage detected
searching dependent graphs…