Rate limit adalah batas akses suatu endpoint dalam waktu tertentu. Misalnya kita hanya memperbolehkan user untuk call endpoint /login
10 kali dalam 1 menit.
Rate limit ini berfungsi untuk menghindarkan server kita dari DDoS (Distributed Denial of Service) yang dapat membuat server kita down dan juga berfungsi untuk menghindarkan kita dari hacker mencari password user dengan melakukan brute force di endpoint login
.
Untuk mengetahui lebih lanjut bagaimana cara menerapkannya, mari baca terus ya sampai selesai dan lebih baik lagi kalau sambil dipraktikkan.
Setup Project
Pertama-tama kita langsung saja membuat project Express.js
. Buat 1 folder misalnya rate-limit-example
dan buka folder tersebut di editor yang kalian pakai. Kalau saya pakai VSCode
.
Kemudian buka terminal dan jalankan command berikut:
yarn init -y
Selanjutnya kita akan install dependencies yang dibutuhkan menggunakan command berikut:
yarn add express redis dotenv
Buat 1 file index.js
yang berisi berikut ini:
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({
message: 'Hello World',
});
});
app.listen(port, () => {
console.log(`App listening on port ${port}`);
});
Jalankan aplikasi dengan command:
node index.js
Kemudian buka http://localhost:3000, maka hasilnya akan muncul:
{ "message": "Hello World" }
Setup Redis
Kalau di komputer kalian belum ada Redis, kalian bisa install sesuai dengan OS komputer kalian dengan mengikuti instruksi Redis Getting Started.
Di tutorial kali ini agar lebih mudah, saya akan menggunakan Redis Labs. Kalau kalian mau coba, bisa ke Redis Labs.
Redis Labs ini di cloud dan ada free-tier-nya, sangat cocok dipakai untuk belajar karena tidak perlu menginstall Redis di komputer local kita.
Redis Client
Kita akan buat Redis Client di aplikasi kita. Buat satu file redis.js
yang berisi berikut:
require('dotenv').config();
const redis = require('redis');
const redisClient = redis.createClient({
url: process.env.REDIS_URL,
});
module.exports = redisClient;
Kemudian kita akan buat 1 file .env
untuk menampung credential Redis kita yang berisi:
REDIS_URL=(Url Redis kalian, kalau Redisnya di local komputer REDIS_URL ini bisa dibiarkan kosong)
Contoh kalau menggunakan Redis Labs:
REDIS_URL=redis://default:MNh4GnWxgQ60JeQMdqDZMBz1qtoWJqyf@redis-17145.c1.ap-southeast-1-1.ec2.cloud.redislabs.com:17145
Rate Limit Middleware
Buat satu file di middlewares/rate-limit.middleware.js
yang berisi berikut:
const redisClient = require('../redis');
const rateLimitMiddleware = (limit, expireTime) => async (
req,
res,
next,
) => {
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
const key = `RATE_LIMIT_${ip}_${req.route.path}`;
const current = await redisClient.incr(key);
if (current > limit) {
return res.status(429).json({
message: 'Too Many Requests',
});
} else if (current === 1) {
await redisClient.expire(key, expireTime);
}
return next();
}
module.exports = rateLimitMiddleware;
Dapat dilihat isi file di atas. Key Redis yang dipakai adalah RATE_LIMIT_{IP}_{Route Path}
. Kalian bisa sesuaikan dengan kebutuhan kalian.
Apply Rate Limit
Ada beberapa code yang harus diubah di file index.js
:
const express = require('express');
const rateLimitMiddleware = require('./middlewares/rate-limit.middleware');
const redisClient = require('./redis');
const app = express();
const port = process.env.PORT || 3000;
const ONE_MINUTE = 60;
(async () => {
await redisClient.connect();
app.get('/', rateLimitMiddleware(10, ONE_MINUTE), (req, res) => {
res.json({
message: 'Hello World',
});
});
app.listen(port, () => {
console.log(`App listening on port ${port}`);
});
})();
Demo
Selanjutnya kita harus restart aplikasi kita:
node index.js
Kemudian coba buka http://localhost:3000 dan refresh sebanyak 11 kali.
Maka akan terkena 429 - Too Many Request
dan setelah kita tunggu 1 menit maka endpoint tersebut akan ke 200 - OK
kembali.
Penutup
Untuk contoh codenya bisa dilihat pada GitHub Repository Rate Limit Example.
Begitulah cara untuk melakukan rate limit menggunakan Redis di aplikasi Express.js kita. Semoga artikel ini bisa bermanfaat bagi teman-teman.