Add rate limits part 2?
This commit is contained in:
parent
3c13bd9550
commit
b878e51994
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -128,3 +128,6 @@ dist
|
||||||
.yarn/build-state.yml
|
.yarn/build-state.yml
|
||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
# Config stuff
|
||||||
|
config.json
|
7
config.json.default
Normal file
7
config.json.default
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"updateInterval": 60,
|
||||||
|
"rateLimiterEnabled": true,
|
||||||
|
"rateLimitWindow": 1,
|
||||||
|
"rateLimitMax": 30,
|
||||||
|
"behindProxy": false
|
||||||
|
}
|
22
index.js
22
index.js
|
@ -13,6 +13,7 @@ I'll try to comment it as best as I can, but I'm not the best at explaining thin
|
||||||
|
|
||||||
const Steam = require("steam-server-query")
|
const Steam = require("steam-server-query")
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
const colors = require("colors");
|
const colors = require("colors");
|
||||||
const semver = require("semver");
|
const semver = require("semver");
|
||||||
const childProcess = require('child_process');
|
const childProcess = require('child_process');
|
||||||
|
@ -342,7 +343,26 @@ setInterval(() => {
|
||||||
updateMasterList();
|
updateMasterList();
|
||||||
}, config.updateInterval * 1000);
|
}, config.updateInterval * 1000);
|
||||||
updateMasterList();
|
updateMasterList();
|
||||||
|
if (config.rateLimiterEnabled) {
|
||||||
|
app.use(rateLimit({
|
||||||
|
windowMs: config.rateLimitWindow * 60 * 1000, // X minutes
|
||||||
|
max: config.rateLimitMax, // limit each IP to X requests per windowMs.
|
||||||
|
keyGenerator: function (req) {
|
||||||
|
return config.behindProxy ? req.headers['x-real-ip'] : req.ip;
|
||||||
|
},
|
||||||
|
skipFailedRequests: true,
|
||||||
|
handler: function (req, res /*, next*/ ) {
|
||||||
|
const remainingTime = Math.round((req.rateLimit.resetTime - Date.now()) / 1000);
|
||||||
|
res.status(429).json({
|
||||||
|
error: 'Too Many Requests',
|
||||||
|
message: `You have exceeded the rate limit. Please try again in ${remainingTime} seconds.`,
|
||||||
|
remainingTime: remainingTime
|
||||||
|
});
|
||||||
|
console.log(`${colors.red(`[ERROR ${new Date()}]`)} ${req.headers["user-agent"]}@${req.ip} exceeded rate limit!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
}
|
||||||
app.get('/check', (req, res) => {
|
app.get('/check', (req, res) => {
|
||||||
// Check that all required parameters are present
|
// Check that all required parameters are present
|
||||||
if (!req.query.address) {
|
if (!req.query.address) {
|
||||||
|
@ -423,6 +443,8 @@ app.get('/', (req, res) => {
|
||||||
"repo": "https://github.com/TerraDevelopers/TerraStatusAPI",
|
"repo": "https://github.com/TerraDevelopers/TerraStatusAPI",
|
||||||
"commit": getGitCommitDetails()
|
"commit": getGitCommitDetails()
|
||||||
},
|
},
|
||||||
|
// Rate limit X requests per Y minutes per IP, as a string
|
||||||
|
"rateLimit": `${config.rateLimitMax} requests per ${config.rateLimitWindow} minutes`,
|
||||||
"debug": {
|
"debug": {
|
||||||
// "yourIP" Either the IP of the user, or the IP of the proxy if one is used, proxy IP header is x-real-ip
|
// "yourIP" Either the IP of the user, or the IP of the proxy if one is used, proxy IP header is x-real-ip
|
||||||
"yourIP": req.headers["x-real-ip"] || req.ip,
|
"yourIP": req.headers["x-real-ip"] || req.ip,
|
||||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -11,6 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"express-rate-limit": "^6.7.0",
|
||||||
"semver": "^7.3.8",
|
"semver": "^7.3.8",
|
||||||
"steam-server-query": "^1.1.3"
|
"steam-server-query": "^1.1.3"
|
||||||
}
|
}
|
||||||
|
@ -207,6 +208,17 @@
|
||||||
"node": ">= 0.10.0"
|
"node": ">= 0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/express-rate-limit": {
|
||||||
|
"version": "6.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
|
||||||
|
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": "^4 || ^5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/finalhandler": {
|
"node_modules/finalhandler": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||||
|
@ -787,6 +799,12 @@
|
||||||
"vary": "~1.1.2"
|
"vary": "~1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"express-rate-limit": {
|
||||||
|
"version": "6.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
|
||||||
|
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"finalhandler": {
|
"finalhandler": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"express-rate-limit": "^6.7.0",
|
||||||
"semver": "^7.3.8",
|
"semver": "^7.3.8",
|
||||||
"steam-server-query": "^1.1.3"
|
"steam-server-query": "^1.1.3"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue