* Handles rate limiting for incoming requests * @param {Object} req - Request object * @param {Function} fn - Optional function to modify rate limit state * @returns {Array} Array containing [valid, limit, remaining, reset]
(req, fn)
| 256 | * @returns {Array} Array containing [valid, limit, remaining, reset] |
| 257 | */ |
| 258 | rateLimit (req, fn) { |
| 259 | const reqId = req.sessionID || req.ip; |
| 260 | let valid = true, |
| 261 | seconds = Math.floor(new Date().getTime() / INT_1000), |
| 262 | limit, remaining, reset, state; |
| 263 | |
| 264 | if (this.rates.has(reqId) === false) { |
| 265 | this.rates.set(reqId, { |
| 266 | limit: this.rate.limit, |
| 267 | remaining: this.rate.limit, |
| 268 | reset: seconds + this.rate.reset, |
| 269 | time_reset: this.rate.reset |
| 270 | }); |
| 271 | } |
| 272 | |
| 273 | if (typeof fn === FUNCTION) { |
| 274 | this.rates.set(reqId, fn(req, this.rates.get(reqId))); |
| 275 | } |
| 276 | |
| 277 | state = this.rates.get(reqId); |
| 278 | limit = state.limit; |
| 279 | remaining = state.remaining; |
| 280 | reset = state.reset; |
| 281 | |
| 282 | if (seconds >= reset) { |
| 283 | reset = state.reset = seconds + this.rate.reset; |
| 284 | remaining = state.remaining = limit - INT_1; |
| 285 | } else if (remaining > INT_0) { |
| 286 | state.remaining--; |
| 287 | remaining = state.remaining; |
| 288 | } else { |
| 289 | valid = false; |
| 290 | } |
| 291 | |
| 292 | return [valid, limit, remaining, reset]; |
| 293 | } |
| 294 | |
| 295 | /** |
| 296 | * Renders the response based on the accepted content type |