express-slow-down
Version:
Basic IP rate-limiting middleware for Express that slows down responses rather than blocking the user.
104 lines (99 loc) • 4.33 kB
JavaScript
// source/slow-down.ts
import { rateLimit } from "express-rate-limit";
var filterUndefinedOptions = (passedOptions) => {
const filteredOptions = {};
for (const k of Object.keys(passedOptions)) {
const key = k;
if (passedOptions[key] !== void 0) {
filteredOptions[key] = passedOptions[key];
}
}
return filteredOptions;
};
var ExpressSlowDownWarning = class extends Error {
constructor(code, message) {
const url = `https://express-rate-limit.github.io/${code}/`;
super(`${message} See ${url} for more information.`);
this.name = this.constructor.name;
this.code = code;
this.help = url;
}
};
var slowDown = (passedOptions = {}) => {
const notUndefinedOptions = filterUndefinedOptions(passedOptions);
if (notUndefinedOptions.headers || notUndefinedOptions.legacyHeaders || notUndefinedOptions.standardHeaders)
throw new Error(
"The headers options were removed in express-slow-down v2.0.0."
);
if (notUndefinedOptions.max !== void 0 || notUndefinedOptions.limit !== void 0)
throw new Error(
"The limit/max option is not supported by express-slow-down, please use delayAfter instead."
);
const validate = typeof notUndefinedOptions.validate === "boolean" ? { default: notUndefinedOptions.validate } : notUndefinedOptions.validate ?? { default: true };
if (typeof notUndefinedOptions.delayMs === "number" && // Make sure the validation check is not disabled.
(validate.delayMs === true || validate.delayMs === void 0 && validate.default)) {
const message = `The behaviour of the 'delayMs' option was changed in express-slow-down v2:
- For the old behavior, change the delayMs option to:
delayMs: (used, req) => {
const delayAfter = req.${notUndefinedOptions.requestPropertyName ?? "slowDown"}.limit;
return (used - delayAfter) * ${notUndefinedOptions.delayMs};
},
- For the new behavior, change the delayMs option to:
delayMs: () => ${notUndefinedOptions.delayMs},
Or set 'options.validate: {delayMs: false}' to disable this message.`.replace(
/^(\t){3}/gm,
""
);
console.warn(new ExpressSlowDownWarning("WRN_ESD_DELAYMS", message));
}
delete validate?.delayMs;
const options = {
// The following settings are defaults that may be overridden by the user's options.
delayAfter: 1,
delayMs(used, request, response) {
const delayAfter = request[options.requestPropertyName].limit;
return (used - delayAfter) * 1e3;
},
maxDelayMs: Number.POSITIVE_INFINITY,
requestPropertyName: "slowDown",
// Next the user's options are pulled in, overriding defaults from above
...notUndefinedOptions,
// This is a combination of the user's validate settings and our own overrides
validate: {
...validate,
limit: false
// We know the behavor of limit=0 changed - we depend on the new behavior!
},
// These settings cannot be overriden.
limit: 0,
// We want the handler to run on every request.
// Disable the headers, we don't want to send them.
legacyHeaders: false,
standardHeaders: false,
// The handler contains the slow-down logic, so don't allow it to be overriden.
async handler(_request, response, next) {
const delayAfter = typeof options.delayAfter === "function" ? await options.delayAfter(_request, response) : options.delayAfter;
const request = _request;
const info = request[options.requestPropertyName];
info.limit = delayAfter;
info.remaining = Math.max(0, delayAfter - info.used);
let delay = 0;
if (info.used > delayAfter) {
const unboundedDelay = typeof options.delayMs === "function" ? await options.delayMs(info.used, request, response) : options.delayMs;
const maxDelayMs = typeof options.maxDelayMs === "function" ? await options.maxDelayMs(request, response) : options.maxDelayMs;
delay = Math.max(0, Math.min(unboundedDelay, maxDelayMs));
}
request[options.requestPropertyName].delay = delay;
if (delay <= 0)
return next();
const timerId = setTimeout(() => next(), delay);
response.on("close", () => clearTimeout(timerId));
}
};
return rateLimit(options);
};
var slow_down_default = slowDown;
export {
slow_down_default as default,
slowDown
};