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