(req: RequestWithRateLimit, res: Response, next: NextFunction)
| 70 | } |
| 71 | |
| 72 | async function middleware(req: RequestWithRateLimit, res: Response, next: NextFunction) { |
| 73 | if (shouldSkip(req, res)) return next() |
| 74 | |
| 75 | const key = keyGenerator(req) |
| 76 | |
| 77 | try { |
| 78 | const { current, resetTime } = await incrementStore(key) |
| 79 | const maxResult = typeof max === 'function' ? await max(req, res) : max |
| 80 | |
| 81 | req.rateLimit = { |
| 82 | limit: maxResult, |
| 83 | current: current, |
| 84 | remaining: Math.max(maxResult - current, 0), |
| 85 | resetTime: resetTime |
| 86 | } |
| 87 | |
| 88 | if (headers && !res.headersSent) { |
| 89 | res.setHeader('X-RateLimit-Limit', maxResult) |
| 90 | res.setHeader('X-RateLimit-Remaining', (req as any).rateLimit.remaining) |
| 91 | if (resetTime instanceof Date) { |
| 92 | // provide the current date to help avoid issues with incorrect clocks |
| 93 | res.setHeader('Date', new Date().toUTCString()) |
| 94 | res.setHeader('X-RateLimit-Reset', Math.ceil(resetTime.getTime() / 1000)) |
| 95 | } |
| 96 | } |
| 97 | if (draftPolliRatelimitHeaders && !res.headersSent) { |
| 98 | res.setHeader('RateLimit-Limit', maxResult) |
| 99 | res.setHeader('RateLimit-Remaining', (req as any).rateLimit.remaining) |
| 100 | if (resetTime) { |
| 101 | const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1000) |
| 102 | res.setHeader('RateLimit-Reset', Math.max(0, deltaSeconds)) |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | if (skipFailedRequests || skipSuccessfulRequests) { |
| 107 | let decremented = false |
| 108 | const decrementKey = () => { |
| 109 | if (!decremented) { |
| 110 | store.decrement(key) |
| 111 | decremented = true |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | if (skipFailedRequests) { |
| 116 | res.on('finish', () => { |
| 117 | if (res.statusCode >= 400) decrementKey() |
| 118 | }) |
| 119 | |
| 120 | res.on('close', () => { |
| 121 | if (!res.writableEnded) decrementKey() |
| 122 | }) |
| 123 | |
| 124 | res.on('error', () => decrementKey()) |
| 125 | } |
| 126 | |
| 127 | if (skipSuccessfulRequests) { |
| 128 | res.on('finish', () => { |
| 129 | if (res.statusCode < 400) store.decrement(key) |
nothing calls this directly
no test coverage detected