Middleware
Middleware adalah function yang bisa digunakan untuk mengakses request object, response object dan next function dalam siklus aplikasi Express.js. Jika Middleware memanggil next function, artinya akan dilanjutkan ke function Middleware selanjutnya atau Router akan dieksekusi.
📚 Middleware Stack

Source: developer.okta.com
✍️ Fungsi Middleware
- Eksekusi kode sebelum sebelum router di eksekusi (misalnya, logging, autentikasi).
- Mengubah Request atau Response object sebelum router di eksekusi (misalnya, menambahkan properti ke
req, mengatur header). - Mengakhiri response tanpa harus mengeksekusi router (misalnya, jika otorisasi gagal, middleware dapat mengirimkan response error 403).
- Memanggil fungsi middleware berikutnya dalam stack dengan memanggil
next(). Jikanext()tidak dipanggil, siklus akan terhenti di middleware tersebut.
💡 Penggunaan Umum Middleware
Middleware sering digunakan untuk:
- Logging (Pencatatan): Mencatat setiap permintaan yang masuk.
- Otentikasi/Otorisasi: Memeriksa apakah pengguna sudah login atau memiliki izin yang tepat sebelum mengizinkan akses ke rute.
- Validasi Data: Memastikan data dalam
req.bodyvalid sebelum data diproses oleh router. - Kompresi: Mengompres response sebelum dikirim ke klien (menggunakan library seperti compression).
📊 Ilustrasi Siklus Request dan Middleware

Source: https://dev.to/ghvstcode/understanding-express-middleware-a-beginners-guide-g73
☝️ Penjelasan Siklus Middleware (Alur Request)
Berikut penjelasan alur siklus Middleware pada contoh kasus di atas pada aplikasi Express.js.
- Klien (Browser/Aplikasi) mengirimkan Request HTTP ke server Express.js.
- Middleware 1 Logging: Request diterima dan melewati middleware pertama (melakukan logging).
- Jika Middleware 1 memanggil
next()dan permintaan berlanjut ke tahap berikutnya. - Jika Middleware 1 mengirimkan response (misalnya,
res.send()), siklus berakhir dan response dikirim kembali ke Klien.
- Jika Middleware 1 memanggil
- Middleware 2 User Auth: Permintaan melewati middleware kedua (melakukan autentikasi)
- Jika autentikasi berhasil Middleware 2, yang mungkin akan menambahkan informasi pengguna ke object
req(misalnya,req.user = user_data) sebelum memanggilnext(). - Jika autentikasi gagal Middleware 2 mengirim response error dan siklus berakhir (misalnya,
res.status(401).send('Unauthorized')ataures.end()).
- Jika autentikasi berhasil Middleware 2, yang mungkin akan menambahkan informasi pengguna ke object
- Middleware 3 JSON Parsing: Permintaan melewati middleware ketiga (melakukan body-parser untuk memproses data JSON).
- Permintaan bergerak ke Middleware 3 JSON Parsing (biasanya menggunakan
express.json()), middleware ini akan menguraikan string JSON tersebut dan mengubahnya menjadi objek JavaScript, menyimpannya direq.body. - Selanjutnya akan memanggil
next().
- Permintaan bergerak ke Middleware 3 JSON Parsing (biasanya menggunakan
- Middleware 4 Static Files: Permintaan mencapai middleware Static Files (biasanya menggunakan
express.static()). Middleware ini memeriksa apakah URL permintaan sesuai dengan file statis (seperti gambar, CSS, atau JavaScript) di folder statis aplikasi.- Jika ditemukan file yang cocok, middleware ini akan mengakhiri siklus dengan segera mengirimkan HTTP Response yang berisi file tersebut.
- Jika tidak ada file statis yang cocok, panggil
next().
- Handler Rute (App Routing): Jika permintaan telah melewati semua middleware dan belum diakhiri, permintaan mencapai App Routing (Penentuan Rute Aplikasi), yaitu handler rute yang sesuai dengan URL permintaan (
app.get('/users', ...)).- Ini adalah tujuan akhir dari permintaan untuk logika bisnis. Handler rute akan memproses permintaan (misalnya, mengambil data dari database).
- Fungsi ini WAJIB mengakhiri siklus dengan mengirimkan HTTP Response (misalnya,
res.send(),res.json(), ataures.render()).
- Mengembalikan HTTP Response: Setelah salah satu fungsi (baik itu middleware statis, handler otentikasi, atau handler rute) mengirimkan response, siklus berakhir, dan HTTP Response dikirim kembali ke klien.
⚙️ Function Middleware
Semua fungsi middleware di Express.js memiliki format dasar:
(req, res, next) => {
// Jalankan kode di sini
console.log('Permintaan masuk pada:', Date.now());
// Panggil next() untuk melanjutkan ke middleware berikutnya atau handler rute
next();
}
req(request): Objek permintaan HTTP.res(response): Objek respons HTTP.next: Fungsi yang dipanggil untuk melanjutkan eksekusi ke fungsi middleware berikutnya. Memanggilnext()sangat penting kecuali middleware tersebut mengakhiri siklus permintaan-response (misalnya, dengan memanggilres.send()).
🧩 Jenis-Jenis Middleware
Middleware dapat digunakan dalam berbagai cara:
1️⃣ Middleware Tingkat Aplikasi (Application-level Middleware)
Diterapkan ke seluruh aplikasi menggunakan app.use(middleware) atau app.METHOD(). Saat kita menerapkan Middleware pada tingkat aplikasi, secara otomatis Middleware itu akan aktif di seluruh route. Apabila kita ingin memakai Middleware hanya untuk route tertentu, kita dapat menambahkan pola route saat mengimplementasikan app.use(), contohnya app.use("/student", middleware).
const express = require('express');
const app = express();
// Middleware ini akan dijalankan untuk SETIAP permintaan ke aplikasi
app.use((req, res, next) => {
console.log(`URL yang diminta: ${req.originalUrl}`);
next();
});
app.get('/', (req, res) => {
res.send('Selamat datang!');
});
2️⃣ Middleware Tingkat Router (Router-level Middleware)
Diterapkan ke instance express.Router(), membatasi fungsinya pada sekumpulan route tertentu. Middleware ini ditambahkan pada object Router yang kita buat dengan express.Router(). Middleware ini akan secara otomatis diaktifkan saat request diterima oleh router ini. Mirip dengan Middleware Tingkat Aplikasi, apabila kita ingin program antara tersebut hanya aktif untuk route tertentu, kita juga bisa menambahkan route path saat menerapkan Middleware ini dengan menggunakan router.use(path, middleware).
const router = express.Router();
// Middleware ini hanya akan dijalankan untuk rute yang menggunakan 'router'
router.use((req, res, next) => {
console.log('Middleware Router berjalan');
next();
});
router.get('/users', (req, res) => {
res.send('Daftar Pengguna');
});
3️⃣ Middleware untuk Penanganan Error (Error-handling Middleware)
Digunakan untuk menangani kesalahan / error yang terjadi di aplikasi kita. Cara penggunaannya serupa dengan Middleware Tingkat Aplikasi, tetapi yang membedakan adalah function callback-nya memiliki empat argumen (err, req, res, next)`. Object error akan secara otomatis terisi dengan informasi mengenai kesalahan yang terjadi dalam aplikasi kita. Middleware ini sangat ideal saat kita ingin menampilkan informasi atau response yang berbeda ketika kesalahan terjadi dalam aplikasi kita.
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Ada yang salah!');
});
4️⃣ Built-in Middleware
Express.js sangat bergantung pada Middleware untuk menangani pemrosesan request dan response, termasuk di dalamnya adalah Built-in Middleware, yaitu middleware yang sudah ada secara default (bawaan) di ExpressJS.
Beberapa Built-in Middleware yang sering digunakan:
| Function | Keterangan |
|---|---|
express.json() | yaitu middleware yang melakukan parsing request body menjadi JavaScript object |
express.text() | yaitu middleware yang melakukan parsing request body menjadi string |
express.raw() | yaitu middleware yang melakukan parsing request body menjadi Buffer |
express.urlencoded() | yaitu middleware yang melakukan parsing request body form menjadi object |
express.static() | yaitu middleware yang digunakan untuk melayani file static |
const express = require('express');
const app = express();
const path = require('path'); // Modul path bawaan Node.js
// Menggunakan express.static() untuk mengakses file dari folder 'public'
// Klien dapat mengakses file di folder ini tanpa menentukan jalur folder 'public' di URL
app.use(express.static(path.join(__dirname, 'public')));
app.listen(3000, () => {
console.log('Server berjalan di http://localhost:3000');
});
5️⃣ Third-party Middleware
Yaitu middleware yang dibuat oleh pihak lain/pihak ketiga. Untuk menggunakannya, kita harus terlebih dahulu menambah dependency middleware-nya ke dalam project kita.
💡 Contoh Penggunaan
- Membuat function Middleware.
// Middleware untuk logging request
const loggerMiddleware = (req, res, next) => {
console.log(`Menerima Request method: ${req.method} ${req.url}`);
next(); // PENTING: Memanggil next() untuk melanjutkan ke handler berikutnya
};
// Middleware untuk menambahkan header X-Powered-By
const poweredHeaderMiddleware = (req, res, next) => {
res.setHeader('X-Powered-By', 'Express Middleware');
next(); // PENTING: Memanggil next() untuk melanjutkan ke handler berikutnya
};
- Menggunakan Middleware.
const app = express();
// Pemanggilan middleware dengan app.use harus sesuai urutan function middleware yang diinginkan
// dan ditempatkan sebelum route handler
app.use(loggerMiddleware);
app.use(poweredHeaderMiddleware);
// Route handler untuk endpoint /hello
app.get('/hello', (req, res) => {
res.send('Hello World!');
});
- Output console log:
Menerima Request method: GET /hello
Jika kita menambahkan route baru, misal dengan endpoint /ucup, maka akan menghasilan log yang sama:
app.get('/hello', (req, res) => {
res.send('Hello World!');
});
app.get('/ucup', (req, res) => {
res.send('Hello Ucup!');
});
Output:
Menerima Request method: GET /hello
Menerima Request method: GET /ucup
🔐 Menambahkan Middleware Query Api Key
// Middleware untuk logging request
const loggerMiddleware = (req, res, next) => {
console.log(`Menerima Request method: ${req.method} ${req.url}`);
next(); // PENTING: Memanggil next() untuk melanjutkan ke handler berikutnya
};
// Middleware untuk menambahkan header X-Powered-By
const poweredHeaderMiddleware = (req, res, next) => {
res.setHeader('X-Powered-By', 'Express Middleware');
next(); // PENTING: Memanggil next() untuk melanjutkan ke handler berikutnya
};
// Middleware untuk validasi API Key
const apiKeyMiddleware = (req, res, next) => {
const apiKey = req.query.apiKey;
if (apiKey && apiKey === 'test123') {
next(); // API key valid, lanjutkan ke handler berikutnya
} else {
res.status(403).end();
}
};
Urutan pemanggilan Middleware diubah setelah logger:
// Pemanggilan middleware dengan app.use harus sesuai urutan function middleware yang diinginkan
// dan ditempatkan sebelum route handler
app.use(loggerMiddleware);
app.use(apiKeyMiddleware); // Middleware untuk validasi API Key setelah logger
app.use(poweredHeaderMiddleware);
// Route handler untuk endpoint /hello
app.get('/hello', (req, res) => {
res.send('Hello World!');
});
app.get('/ucup', (req, res) => {
res.send('Hello Ucup!');
});
📝 Manipulasi Request
Karena Request itu adalah JavaScript Object, kita juga bisa memanipulasi Request Object di Middleware. Misalnya mengubah attribute atau menambah attribute baru, agar bisa digunakan di Middleware selanjutnya, atau di Route.
// Middleware untuk menambahkan waktu request
const timeMiddleware = (req, res, next) => {
req.requestTime = Date.now();
next();
}
Memanggil Middleware:
// Pemanggilan middleware dengan app.use harus sesuai urutan function middleware yang diinginkan
// dan ditempatkan sebelum route handler
app.use(loggerMiddleware);
app.use(apiKeyMiddleware); // Middleware untuk validasi API Key setelah logger
app.use(poweredHeaderMiddleware);
app.use(timeMiddleware); // Middleware untuk menambahkan waktu request
Memanggil request di router:
app.get('/time', (req, res) => {
const currentTime = req.requestTime; // Mengambil waktu (requestTime) dari middleware dateTimeMiddleware
res.send(`Request received at: ${currentTime}`);
});
🔥 Fullcode dengan Unit Test
const request = require('supertest');
const express = require('express');
// Middleware untuk logging request
const loggerMiddleware = (req, res, next) => {
console.log(`Menerima Request method: ${req.method} ${req.url}`);
next(); // PENTING: Memanggil next() untuk melanjutkan ke handler berikutnya
};
// Middleware untuk menambahkan header X-Powered-By
const poweredHeaderMiddleware = (req, res, next) => {
res.setHeader('X-Powered-By', 'Express Middleware');
next(); // PENTING: Memanggil next() untuk melanjutkan ke handler berikutnya
};
// Middleware untuk validasi API Key
const apiKeyMiddleware = (req, res, next) => {
const apiKey = req.query.apiKey;
if (apiKey && apiKey === 'test123') {
next(); // API key valid, lanjutkan ke handler berikutnya
} else {
res.status(403).end();
}
};
// Middleware untuk menambahkan waktu request
const timeMiddleware = (req, res, next) => {
req.requestTime = Date.now();
next();
}
const app = express();
// Pemanggilan middleware dengan app.use harus sesuai urutan function middleware yang diinginkan
// dan ditempatkan sebelum route handler
app.use(loggerMiddleware);
app.use(apiKeyMiddleware); // Middleware untuk validasi API Key setelah logger
app.use(poweredHeaderMiddleware);
app.use(timeMiddleware); // Middleware untuk menambahkan waktu request
// Route handler untuk endpoint /hello
app.get('/hello', (req, res) => {
res.send('Hello World!');
});
app.get('/ucup', (req, res) => {
res.send('Hello Ucup!');
});
app.get('/time', (req, res) => {
const currentTime = req.requestTime; // Mengambil waktu (requestTime) dari middleware dateTimeMiddleware
res.send(`Request received at: ${currentTime}`);
});
// Test untuk middleware dan endpoint /hello
test('Test Response Middleware /hello endpoint', async () => {
const response = await request(app).get('/hello').query({ apiKey: 'test123' });
expect(response.headers['x-powered-by']).toBe('Express Middleware');
expect(response.status).toBe(200);
expect(response.text).toBe('Hello World!');
});
test('Test Response Middleware /ucup endpoint', async () => {
const response = await request(app).get('/ucup').query({ apiKey: 'test123' });
expect(response.headers['x-powered-by']).toBe('Express Middleware');
expect(response.status).toBe(200);
expect(response.text).toBe('Hello Ucup!');
});
test('Test Response Middleware Unauthorized /ucup endpoint', async () => {
const response = await request(app).get('/ucup');
expect(response.status).toBe(403);
});
test('Test Response Middleware Time /time endpoint', async () => {
const response = await request(app).get('/time').query({ apiKey: 'test123' });
expect(response.headers['x-powered-by']).toBe('Express Middleware');
expect(response.status).toBe(200);
expect(response.text).toContain('Request received at:'); // Menggunakan toContain karena waktu akan berubah-ubah setiap request
});