added rate limiting
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
import stringify from 'json-stringify-safe';
|
||||
|
||||
import {Logger} from '../models/logger';
|
||||
import {Logger} from '../../models/logger';
|
||||
|
||||
export class MiddleWare {
|
||||
static async end(req, res, next) {
|
||||
await MiddleWare.RateLimits.request(req, res, next);
|
||||
await MiddleWare.analytics(req, res, next);
|
||||
}
|
||||
|
||||
static analytics(req, res, next) {
|
||||
// TODO: Send data such as IP to an anyaltitics model
|
||||
Logger.middleware(`${req.method} request to ${req.url}`)
|
||||
@@ -13,3 +18,5 @@ export class MiddleWare {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
MiddleWare.RateLimits = require('./rateLimits').RateLimits;
|
||||
53
src/controllers/middleware/rateLimits.js
Normal file
53
src/controllers/middleware/rateLimits.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import {Logger} from '../../models/logger';
|
||||
import {MiddleWare} from './index';
|
||||
|
||||
let requestsPerSecond = 2;
|
||||
// let disposeTime = 20000; //ms 1800000 = 30 mins
|
||||
let buckets = {}
|
||||
|
||||
export class RateLimits extends MiddleWare{
|
||||
static async request(req, res, next) {
|
||||
let ip = req.connection.remoteAddress;
|
||||
|
||||
if (!buckets[ip]) {
|
||||
console.log(`New bucket`)
|
||||
RateLimits.newBucket(ip);
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
buckets[ip].lastUsed = new Date().getTime();
|
||||
|
||||
if (buckets[ip].tokens.length <= 0) {
|
||||
Logger.middleware(`${ip} is being rate limited`);
|
||||
res.status(422).end('422 TO MANY REQUESTS');
|
||||
return;
|
||||
}
|
||||
|
||||
buckets[ip].tokens.pop();
|
||||
next();
|
||||
}
|
||||
|
||||
static newBucket(ip) {
|
||||
buckets[ip] = {ip: ip, tokens: [], lastUsed: new Date().getTime()};
|
||||
for (let i = 0; i < requestsPerSecond; i++) {
|
||||
buckets[ip].tokens.push(1);
|
||||
}
|
||||
}
|
||||
|
||||
static tick() {
|
||||
for (let bucket in buckets) {
|
||||
// if (buckets[bucket].lastUsed += disposeTime >= new Date().getTime()) {
|
||||
// delete buckets[bucket]; // remove element here, don't redefine
|
||||
// continue;
|
||||
// }
|
||||
if (buckets[bucket].tokens.length > requestsPerSecond) continue;
|
||||
buckets[bucket].tokens.push(1);
|
||||
}
|
||||
}
|
||||
|
||||
static init() {
|
||||
Logger.info('Initialized ratelimiting middleware');
|
||||
setInterval(RateLimits.tick, 1000 / requestsPerSecond);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Logger} from '../../models/logger';
|
||||
import {Server} from '../../server';
|
||||
import {MiddleWare} from '../middleware';
|
||||
import {MiddleWare} from '../middleware/index';
|
||||
import {StatusCodes} from '../status';
|
||||
import {Controllers} from '../index';
|
||||
|
||||
@@ -12,11 +12,11 @@ export class Router {
|
||||
|
||||
app = Server.App;
|
||||
|
||||
app.get('/', [MiddleWare.analytics, Router.frontPage]);
|
||||
app.get('/', [MiddleWare.end, Router.frontPage]);
|
||||
|
||||
app.get('/user/:id', [MiddleWare.analytics]);
|
||||
app.delete('/user/:id', [MiddleWare.analytics]);
|
||||
app.post('/user', [MiddleWare.analytics, Controllers.UserController.newUser]);
|
||||
app.get('/user/:id', [MiddleWare.end]);
|
||||
app.delete('/user/:id', [MiddleWare.end]);
|
||||
app.post('/user', [MiddleWare.end, Controllers.UserController.newUser]);
|
||||
|
||||
app.use([StatusCodes.pageNotFound]);
|
||||
Logger.info('HTTP endpoints settup');
|
||||
|
||||
@@ -31,12 +31,15 @@ export class UserController extends ControllerHandler {
|
||||
if (errors.count() > 0) {
|
||||
errors.endpoint();
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
let success = new User(id, username, password, email, ip, 1234).insert();
|
||||
let user = new User(id, username, password, email, ip, 1234)
|
||||
let success = await user.insert();
|
||||
if (success == -1) {
|
||||
errors.addError(500, 'Internal server error', 'An error occured with the databse').endpoint();
|
||||
errors.addError(500, 'Internal server error').endpoint();
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
new API.user(res, id, username, email, new Date().toLocaleString(), token).endpoint();
|
||||
|
||||
Reference in New Issue
Block a user