Rate Limiting in Express

Piyush Dubey
Webtips
Published in
6 min readFeb 6, 2021

--

Hey There, Hope you guys are doing well. Today we will be discussing how we can limit the rate request on a particular API, we call this terminology a Rate-Limiting.

Photo by Matt Seymour on Unsplash

Definition

Rate-limiting in API is used to control the rate of requests sent by clients having the same IP. It can be used to prevent Proxy data or DoS attacks and limit web scraping for the content.

Prerequisite

To make use of this article at the peak, one needs to know

  • What is an API?

API(Application Programming Interface) is the communication unit between client and data (Can be database). You can think of a waiter as an API whereas data is a dish that is made by the chef and client as a customer.

  • What are the Middlewares?

Before going to the actual logic to extract data for a client, a server can perform several other actions. for example, checking the validity of the request (For data consistency), caching the data and sending that data, checking the user headers (For security concerns), blocking a particular IP (Which is we are going to use today), etc.

Usecase

You will find many traditional definitions online but let’s discuss an actual scenario where you can make use of limiting the rate.

Let’s assume, you are a businessman of cars(Put whatever big brand you want to put here) and now you want to give a virtual demo for your client using videos on your website. You hire a service provider which is going to give you 1000 requests per month as your new trial as per your client base and business needs.

Now, after getting live with this feature you notice some of your clients are exhausting your 1000 limit as they are re-watching the video sessions. So you made a decision to let the user rewatch the video but not repeatedly or they can watch the video again after 30 seconds.

To achieve this result you came to me and I started making it a reality by adding another middleware into your system.

Get Started

Create App

Let’s create the above use-case into reality.

To begin, first create a folder here I name it rate-limiting-demo and open the vscode with the integrated terminal.

Once you open the terminal type a command

npm init -y

which will create a new project with the default settings, you can always go to your package.json file to make any necessary changes.

Next,

create a few folders and files

1. Index.js — entry point for the application 2. controllers, routes and middleware folder
folder structure for the project

After creating the folder we can simply create our express application

npm i express

The above command will install the express in your folder then go ahead to your index.js and write a bunch of starters and default routes.

import express from 'express';const app = express();const PORT = 8080;
// create a route for the appapp.get('/', (req, res) => { res.send('Hello World');});
// default routeapp.use((req, res) => { res.status(404).send({ message : 'URL Not found!' })})// make the server listen to requests
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);});

and If you try to run your application using command node index then it will fail as we are not using commonJS syntax.

Error of not using commonJs

To make sure no error is prompt up we can add one line in our package.json

"type" : "module"

After writing this your package.json will look like this,

Package.json file

Now, if you run the application it will start listening at PORT 8080.

Add a Route and Controller

Now, go to the /routes folder and create an index.js file and paste this code

import { Router } from 'express';var router = Router();router.get('/video', function (req, res) {      res.send('video sent');})export default router;

This will use an express router and attach another route ‘/video’ to it.

now move to the index.js and include this file there.

first, we need to import the file

import apiRouter from "./routes/index.js";

then before our default response use the apiRouter we just created

app.use('/api', apiRouter)

Once we include these lines our index.js will look like this

index.js file with the router included

Now, let’s create an index.js file in the /controllers folder and paste this code

let remainingCounter = 1000;class VideoStreamer {      validator = (req, res, next) => {                   next()       }       video = () => {               return 'your controlled video stream'       }       getVideo = (req, res) => {                   let video = this.video()                   remainingCounter = remainingCounter - 1;                   res.status(200).send({                        message : `Remaining count for video is                           ${remainingCounter}`,                         video                   })       }}export default new VideoStreamer();

and here is a screenshot of the code for better readability,

controller logic for the code

Let me deconstruct the code for you,

here we have created a class name VideoStreamer which will be handling our entire logic of the code and we have exported the class but don’t forget to export a new object from it

next, we have created a global variable named remainingCounter which is behaving as our total limit for the videos

We have also added 2 methods named getVideo(We are only sending the response with reducing the counter to -1) and validator(this will be our one of the middleware)

Note: This is not a tutorial for creating a counter application using express and MongoDB. So I have avoided that logic + I separate out streaming logic to independent functions to not mess with the actual topic.

Hope you understand the code :)

Next, Change the /routes/index.js to include the controller file

import Controller from './../controllers/index.js';

and update our route to new methods

router.get('/video', Controller.validator, Controller.getVideo)

After this step, our /routes/index.js will look like this,

Sober.

If we now run the application and go to the URL

http://localhost:8080/api/video

We will see this result

browser view for api

And every time we refresh the page, it will reduce the count

to -1, which is exactly what we are facing as a challenge in our use case.

Create Rate-Limiter

Now it’s time to create our rate limiter which will help us to reduce our issue.

first, install the package express-rate-limit which will be giving us the flexibility to write the efficient limiter.

npm install --save express-rate-limit

create /middlewares/rateLimiter.js file and paste the bunch of code there

import rateLimit from "express-rate-limit";const limiter = rateLimit({                  windowMs: 6 * 1000, // 6 seconds                  max: 2 // limit each IP to 2 requests per windowMs                });export default limiter;

The above code will freeze the window for 6 seconds once the 2 limits are reached, it will send the code 429 with the default message which you can configure.

Let’s attach this function to our route. Head back to the /routes/index.js and add one more middleware after importing the file.

import rateLimiter from './../middlewares/rateLimiter.js';

and updated route,

router.get('/video', rateLimiter, Controller.validator, Controller.getVideo)

The final result will look like this,

final result for routes

Now, if you go back to the browser, you will see a different result as your account will be blocked after a few successive results.

Browser final inspector

And here we will conclude that now you know a use case where you can use rate-limiting.

I hope you guys like this article. Please like and share to the one who is looking for rate limiter :) Have a great day. Thanks!

--

--