Middleware adalah function yang dijalankan Express di antara request masuk dan handler route. Dia bisa membaca atau menambah sesuatu ke req, menghentikan request dengan langsung menjawab, atau mengoper ke yang berikutnya dengan next(). Bayangin pintu masuk konser: tiket dicek, tas diperiksa, gelang dipasang, baru kamu masuk ke venue. Tiap pos bisa bilang "silakan lanjut" atau "stop, gak boleh masuk". Kalau satu petugas lupa mempersilakan, kamu berdiri di situ terus.
🧪 Tebakan cepat: middleware
loggermencetakGET /catatanke terminal, tapi lupa memanggilnext(). Apa yang diterimacurl? Tebak dulu, jawabannya ada di bagian "next(): oper ke yang berikutnya".
Middleware: function dengan req, res, next
const express = require("express");
const app = express();
app.use(express.json());
function logger(req, res, next) {
console.log(req.method + " " + req.url);
next();
}
app.use(logger);
app.get("/catatan", (req, res) => {
res.json(catatan);
});
- Middleware punya parameter ketiga,
next: function untuk mengoper request ke middleware atau handler berikutnya. app.use(logger)memasangloggeruntuk semua request, apa pun method dan path-nya.app.use(express.json())juga middleware: bawaan Express yang membaca body JSON dan menaruhnya direq.body.
Setelah node app.js, dua request ke server menghasilkan ini di terminal server:
Server jalan di http://localhost:3000
GET /catatan
POST /catatan
next(): oper ke yang berikutnya
Tiap middleware harus melakukan salah satu dari dua hal: memanggil next(), atau mengirim jawaban (res.json, res.send, ...). Kalau logger cuma mencetak tanpa next(), terminal server tetap menulis GET /catatan, tapi request berhenti di situ. Handler gak pernah jalan, jawaban gak pernah dikirim, dan curl menunggu terus. Dengan batas waktu 5 detik (curl -i -m 5 http://localhost:3000/catatan):
curl: (28) Operation timed out after 5002 milliseconds with 0 bytes received
Gak ada error di server, request-nya cuma menggantung. Itu jawaban tebakannya.
Urutan = urutan app.use
Express menjalankan middleware dan route sesuai urutan kamu menulisnya:
app.use((req, res, next) => { console.log("A"); next(); });
app.use((req, res, next) => { console.log("B"); next(); });
app.get("/", (req, res) => { res.send("C"); });
GET / mencetak A lalu B di terminal, lalu handler mengirim C ke browser. Kebalikannya juga berlaku: middleware yang ditulis setelah sebuah route gak dijalankan untuk request yang sudah dijawab route itu, karena route-nya gak memanggil next().
Middleware penjaga untuk satu route
Membuat catatan baru cuma boleh untuk yang bawa API key. Penjaganya middleware juga:
function cekApiKey(req, res, next) {
if (req.headers["x-api-key"] !== "rahasia123") {
return res.status(401).json({ error: "API key tidak valid" });
}
next();
}
app.post("/catatan", cekApiKey, (req, res) => {
const { judul, isi } = req.body;
const baru = { id: catatan.length + 1, judul, isi };
catatan.push(baru);
res.status(201).json(baru);
});
Header x-api-key |
Yang terjadi | Jawaban |
|---|---|---|
| gak ada | penjaga menjawab, next() gak dipanggil |
401 {"error":"API key tidak valid"} |
salah |
sama | 401 {"error":"API key tidak valid"} |
rahasia123 |
next(), handler jalan |
201 {"id":3,"judul":"Olahraga","isi":"lari 5 km"} |
- Middleware ditaruh di antara path dan handler:
app.post(path, cekApiKey, handler). Cuma route ini yang dijaga,GET /catatantetap bebas. 401 Unauthorizedartinya "kamu belum membuktikan siapa dirimu".- Node menyimpan nama header dengan huruf kecil. Dikirim
X-API-Keypun, bacanyareq.headers["x-api-key"].req.get("x-api-key")juga bisa, dan gak peduli huruf besar kecil.
Middleware siap pakai
| Middleware | Gunanya |
|---|---|
express.json() |
membaca body JSON jadi req.body |
express.urlencoded({ extended: true }) |
membaca body dari form HTML |
helmet |
memasang security headers seperti Content-Security-Policy dan X-Frame-Options |
cors |
mengatur domain mana yang boleh memanggil API dari browser |
morgan |
mencatat tiap request ke terminal, seperti logger kita |
express-rate-limit |
membatasi jumlah request per IP, misalnya 100 per menit |
Yang dari npm dipasang dulu (npm install helmet), lalu app.use(helmet()).
📌 Express 5: error di middleware async
Kalau middleware atau handler async melempar error, Express 5 otomatis meneruskannya ke penanganan error dan menjawab 500. Express 4 gak melakukannya: error itu jadi unhandled rejection, dan Node mematikan server-nya. Cara menangani error-nya sendiri ada di pelajaran Error Handling.
Di latihan: penjaga sebagai function biasa
Latihannya gak menjalankan Express. checkApiKey(headers) menerima object header dan cuma menjawab true atau false: return headers["x-api-key"] === "rahasia123";. Yang mencetak kalimatnya adalah kode di bawahnya, yang sudah ada di kode awal:
Request dengan key valid: Akses diberikan - Ini data rahasia
Request tanpa key: Akses ditolak - API key tidak valid
⚠️ Jebakan yang sering ketemu
- Lupa
next(). Request menggantung tanpa error, sampai klien menyerah. - Lupa
returndi penjaga.res.status(401).json(...)tanpareturndiikutinext(): klien dapat 401, tapi handler tetap jalan dan catatannya tetap tersimpan. Terminal server lalu menulisError [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. app.use(logger)ditulis setelah route. Request yang sudah dijawab route gak pernah sampai kelogger.- Nama header huruf besar.
req.headers["X-API-Key"]selaluundefined. Tulis huruf kecil.
TL;DR: Middleware adalah function (req, res, next) yang jalan sebelum handler, dan tiap middleware harus memanggil next() atau mengirim jawaban. Tanpa keduanya request menggantung (curl: (28) Operation timed out). app.use(fn) memasangnya untuk semua route, sesuai urutan ditulis (A lalu B lalu handler). app.post("/catatan", cekApiKey, handler) menjaga satu route saja, dan penjaga menolak dengan return res.status(401).json(...), pakai return. Header dibaca dengan huruf kecil: req.headers["x-api-key"]. express.json() membaca body, helmet memasang security headers, cors, morgan, dan express-rate-limit menyusul dari npm. Express 5 meneruskan error dari middleware async, Express 4 gak.