(checks, log)
| 161 | } |
| 162 | |
| 163 | function checkRateLimitsForRequest(checks, log) { |
| 164 | const buckets = []; |
| 165 | for (const check of checks) { |
| 166 | const bucket = getTokenBucket(check.resourceClass, check.resourceId, check.measure, check.config, log); |
| 167 | if (!bucket.hasCapacity()) { |
| 168 | log.debug('Rate limit check: denied (no tokens available)', { |
| 169 | resourceClass: check.resourceClass, |
| 170 | resourceId: check.resourceId, |
| 171 | measure: check.measure, |
| 172 | limit: check.config.limit, |
| 173 | source: check.source, |
| 174 | }); |
| 175 | |
| 176 | return { allowed: false, rateLimitSource: `${check.resourceClass}:${check.source}`}; |
| 177 | } |
| 178 | |
| 179 | buckets.push(bucket); |
| 180 | |
| 181 | log.trace('Rate limit check: allowed (token consumed)', { |
| 182 | resourceClass: check.resourceClass, |
| 183 | resourceId: check.resourceId, |
| 184 | measure: check.measure, |
| 185 | source: check.source, |
| 186 | }); |
| 187 | } |
| 188 | |
| 189 | // buckets have already been checked for available capacity |
| 190 | // no need to check return values |
| 191 | buckets.forEach(bucket => bucket.tryConsume()); |
| 192 | return { allowed: true }; |
| 193 | } |
| 194 | |
| 195 | module.exports = { |
| 196 | rateLimitApiActions, |
no test coverage detected