Aktueller Stand
This commit is contained in:
50
backend/node_modules/@fastify/rate-limit/store/LocalStore.js
generated
vendored
Normal file
50
backend/node_modules/@fastify/rate-limit/store/LocalStore.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
'use strict'
|
||||
|
||||
const { LruMap: Lru } = require('toad-cache')
|
||||
|
||||
function LocalStore (continueExceeding, exponentialBackoff, cache = 5000) {
|
||||
this.continueExceeding = continueExceeding
|
||||
this.exponentialBackoff = exponentialBackoff
|
||||
this.lru = new Lru(cache)
|
||||
}
|
||||
|
||||
LocalStore.prototype.incr = function (ip, cb, timeWindow, max) {
|
||||
const nowInMs = Date.now()
|
||||
let current = this.lru.get(ip)
|
||||
|
||||
if (!current) {
|
||||
// Item doesn't exist
|
||||
current = { current: 1, ttl: timeWindow, iterationStartMs: nowInMs }
|
||||
} else if (current.iterationStartMs + timeWindow <= nowInMs) {
|
||||
// Item has expired
|
||||
current.current = 1
|
||||
current.ttl = timeWindow
|
||||
current.iterationStartMs = nowInMs
|
||||
} else {
|
||||
// Item is alive
|
||||
++current.current
|
||||
|
||||
// Reset TLL if max has been exceeded and `continueExceeding` is enabled
|
||||
if (this.continueExceeding && current.current > max) {
|
||||
current.ttl = timeWindow
|
||||
current.iterationStartMs = nowInMs
|
||||
} else if (this.exponentialBackoff && current.current > max) {
|
||||
// Handle exponential backoff
|
||||
const backoffExponent = current.current - max - 1
|
||||
const ttl = timeWindow * (2 ** backoffExponent)
|
||||
current.ttl = Number.isSafeInteger(ttl) ? ttl : Number.MAX_SAFE_INTEGER
|
||||
current.iterationStartMs = nowInMs
|
||||
} else {
|
||||
current.ttl = timeWindow - (nowInMs - current.iterationStartMs)
|
||||
}
|
||||
}
|
||||
|
||||
this.lru.set(ip, current)
|
||||
cb(null, current)
|
||||
}
|
||||
|
||||
LocalStore.prototype.child = function (routeOptions) {
|
||||
return new LocalStore(routeOptions.continueExceeding, routeOptions.exponentialBackoff, routeOptions.cache)
|
||||
}
|
||||
|
||||
module.exports = LocalStore
|
||||
58
backend/node_modules/@fastify/rate-limit/store/RedisStore.js
generated
vendored
Normal file
58
backend/node_modules/@fastify/rate-limit/store/RedisStore.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
'use strict'
|
||||
|
||||
const lua = `
|
||||
-- Key to operate on
|
||||
local key = KEYS[1]
|
||||
-- Time window for the TTL
|
||||
local timeWindow = tonumber(ARGV[1])
|
||||
-- Max requests
|
||||
local max = tonumber(ARGV[2])
|
||||
-- Flag to determine if TTL should be reset after exceeding
|
||||
local continueExceeding = ARGV[3] == 'true'
|
||||
--Flag to determine if exponential backoff should be applied
|
||||
local exponentialBackoff = ARGV[4] == 'true'
|
||||
|
||||
--Max safe integer
|
||||
local MAX_SAFE_INTEGER = (2^53) - 1
|
||||
|
||||
-- Increment the key's value
|
||||
local current = redis.call('INCR', key)
|
||||
|
||||
if current == 1 or (continueExceeding and current > max) then
|
||||
redis.call('PEXPIRE', key, timeWindow)
|
||||
elseif exponentialBackoff and current > max then
|
||||
local backoffExponent = current - max - 1
|
||||
timeWindow = math.min(timeWindow * (2 ^ backoffExponent), MAX_SAFE_INTEGER)
|
||||
redis.call('PEXPIRE', key, timeWindow)
|
||||
else
|
||||
timeWindow = redis.call('PTTL', key)
|
||||
end
|
||||
|
||||
return {current, timeWindow}
|
||||
`
|
||||
|
||||
function RedisStore (continueExceeding, exponentialBackoff, redis, key = 'fastify-rate-limit-') {
|
||||
this.continueExceeding = continueExceeding
|
||||
this.exponentialBackoff = exponentialBackoff
|
||||
this.redis = redis
|
||||
this.key = key
|
||||
|
||||
if (!this.redis.rateLimit) {
|
||||
this.redis.defineCommand('rateLimit', {
|
||||
numberOfKeys: 1,
|
||||
lua
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
RedisStore.prototype.incr = function (ip, cb, timeWindow, max) {
|
||||
this.redis.rateLimit(this.key + ip, timeWindow, max, this.continueExceeding, this.exponentialBackoff, (err, result) => {
|
||||
err ? cb(err, null) : cb(null, { current: result[0], ttl: result[1] })
|
||||
})
|
||||
}
|
||||
|
||||
RedisStore.prototype.child = function (routeOptions) {
|
||||
return new RedisStore(routeOptions.continueExceeding, routeOptions.exponentialBackoff, this.redis, `${this.key}${routeOptions.routeInfo.method}${routeOptions.routeInfo.url}-`)
|
||||
}
|
||||
|
||||
module.exports = RedisStore
|
||||
Reference in New Issue
Block a user