This is too often overlooked or completely ignored. But just a few lines of code can make your app much harder to break.
import helmet from "helmet";
export const createApp = () => {
// ...
app.use(helmet());
app.use(helmet.noCache()); // disable browser caching
app.use(
helmet.hsts({
includeSubDomains: true, // enforce https everywhere
preload: true
})
);
// ...
};
$ yarn add rate-limiter-flexible
.
├── app.ts
└── middlewares
├── RateLimiter
│  ├── index.spec.ts
│  └── index.ts
└── index.ts
import { RateLimiterMemory, IRateLimiterOptions } from 'rate-limiter-flexible';
import { Handler } from 'express';
import { AppRequest } from '../app';
class RateLimiterMiddleware extends RateLimiterMemory {
constructor(opts: IRateLimiterOptions = {}) {
super({
points: 10,
duration: 1,
...opts,
});
}
middleware: Handler = async (request: AppRequest, response, next) => {
try {
await this.consume(request.user ? request.user.emailAddress : request.ip);
next();
} catch (error) {
response.sendStatus(429); // Too Many Requests
}
};
}
export { RateLimiterMiddleware };
export * from './RateLimiter'
import { RateLimiterMiddleware } from './middlewares'
export const createApp = () => {
const app = express();
app.use(new RateLimiterMiddleware().middleware);
};
The number of requests is now limited to 10 per seconds. Go ahead an experiment with higher numbers to see if you will get rejected.
$ yarn add supertest @types/supertest -D
middlewares/RateLimiter/index.spec.ts
import * as express from "express";
import * as supertest from "supertest";
import { RateLimiterMiddleware } from "./index";
describe("middlewares/RateLimiter", () => {
it("should limit the amount of requests", async () => {
const app = express();
app.use(new RateLimiterMiddleware({ points: 1 }).middleware);
app.get("/test", (_, response) => response.sendStatus(200));
const agent = supertest(app);
await agent.get("/test").expect(200);
await agent.get("/test").expect(429);
});
});