express-rate-limit adalah pustaka middleware pihak ketiga untuk kerangka kerja Express.js di Node.js yang berfungsi untuk membatasi jumlah permintaan (request) berulang dari alamat IP yang sama ke sebuah server dalam jangka waktu tertentu. Pustaka ini sangat esensial untuk mengamankan API dari serangan brute-force, denial-of-service (DoS), atau penggunaan bot yang berlebihan.
Cara kerjanya adalah dengan mencatat aktivitas IP klien menggunakan penyimpanan memori bawaan (memory store) atau penyimpanan eksternal seperti Redis. Jika jumlah permintaan melampaui batas yang ditentukan (misalnya 100 permintaan per 15 menit), peladen akan menghentikan proses dan mengembalikan kode status HTTP 429 Too Many Requests.
Instalasi dan Konfigurasi Dasar
Untuk memulai, pastikan proyek Node.js Anda sudah terinstal Express. Jalankan perintah terminal berikut untuk memasang paket express-rate-limit:
npm install express-rate-limit
Berikut adalah contoh implementasi dasar dalam kode server Express:
const express = require('express');
const { rateLimit } = require('express-rate-limit');
const app = express();
// Konfigurasi pembatas laju dasar
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 menit
max: 100, // Batasi setiap IP hingga 100 permintaan per windowMs
message: 'Terlalu banyak permintaan dari IP ini, silakan coba lagi setelah 15 menit',
standardHeaders: true, // Mengirimkan header pembatas laju standar (RateLimit-*)
legacyHeaders: false, // Menonaktifkan header X-RateLimit-*
});
// Terapkan pembatas laju ke semua rute
app.use(limiter);
app.get('/', (req, res) => {
res.send('Halo, dunia!');
});
app.listen(3000, () => {
console.log('Server berjalan pada port 3000');
});
Parameter Konfigurasi Utama
Pustaka ini menyediakan berbagai opsi parameter untuk menyesuaikan kebutuhan keamanan aplikasi Anda. Berikut adalah tabel parameter yang paling sering digunakan:
| Parameter | Tipe Data | Keterangan |
|---|---|---|
windowMs |
Number | Durasi waktu dalam milidetik untuk pelacakan ulang batas permintaan. |
max |
Number / Function | Jumlah maksimum permintaan yang diizinkan per IP dalam rentang windowMs. |
message |
String / JSON / Any | Respons yang dikirimkan ketika batas terlampaui. |
statusCode |
Number | Kode status HTTP yang dikembalikan saat batas terlampaui (default: 429). |
skip |
Function | Fungsi untuk melewati (skip) pembatasan berdasarkan kondisi tertentu (misal: IP lokal). |
store |
Object | Media penyimpanan data hit (default menggunakan MemoryStore). |
Penerapan pada Rute Tertentu (Endpoint Specific)
Seringkali pembatasan tidak perlu diterapkan ke seluruh aplikasi, melainkan hanya pada rute sensitif seperti halaman login atau pendaftaran akun untuk mencegah serangan kredensial.
const { rateLimit } = require('express-rate-limit');
// Pembatasan khusus untuk rute login
const loginLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 jam
max: 5, // Batasi 5 kali percobaan login per jam
message: { status: 429, error: 'Terlalu banyak percobaan login, coba lagi nanti.' },
standardHeaders: true,
legacyHeaders: false,
});
// Terapkan hanya pada endpoint /api/login
app.post('/api/login', loginLimiter, (req, res) => {
// Logika autentikasi di sini
res.send('Proses login...');
});
Menggunakan Redis untuk Skala Banyak Server (Cluster/Load Balancer)
Secara default, express-rate-limit menggunakan penyimpanan memori lokal. Jika aplikasi Anda berjalan di banyak instans (seperti di Docker, Kubernetes, atau menggunakan load balancer), memori lokal tidak akan sinkron antar server. Anda memerlukan penyimpanan eksternal seperti Redis menggunakan pustaka tambahan rate-limit-redis.
npm install express-rate-limit rate-limit-redis redis
Contoh integrasi dengan Redis:
const { createClient } = require('redis');
const { rateLimit } = require('express-rate-limit');
const { RedisStore } = require('rate-limit-redis');
// Inisialisasi klien Redis
const client = createClient();
client.connect().catch(console.error);
const redisLimiter = rateLimit({
store: new RedisStore({
sendCommand: (...args) => client.call(...args),
}),
windowMs: 15 * 60 * 1000,
max: 100,
});
app.use(redisLimiter);
Troubleshooting Masalah IP Asli di Balik Proxy
Jika aplikasi Node.js Anda berada di belakang reverse proxy seperti Nginx, Cloudflare, atau AWS ELB, alamat IP yang terdeteksi oleh Express akan selalu berupa IP lokal peladen (127.0.0.1) atau IP proxy tersebut, bukan IP asli pengguna.
Untuk mengatasi hal ini, Anda harus mengaktifkan pengaturan trust proxy pada aplikasi Express sebelum menerapkan pembatas laju:
// Beritahu Express untuk percaya pada proxy pertama
app.set('trust proxy', 1);
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
});
app.use(limiter);