added rate limiting

This commit is contained in:
Ben
2018-09-01 19:57:51 +01:00
parent c33f7bdd7b
commit 8ef777ae44
8 changed files with 82 additions and 17 deletions

View File

@@ -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;

View 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);
}
}

View File

@@ -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');

View File

@@ -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();