Middleware di Express adalah fungsi dengan signature (req, res, next) yang berjalan di antara saat request tiba dan saat response dikirim. Setiap middleware bisa membaca atau mengubah req dan res, mengakhiri request dengan mengirim response, atau memanggil next() untuk menyerahkan request ke fungsi berikutnya dalam antrean. app.use(fn) menambahkan middleware untuk setiap request, dan Express menjalankan semuanya sesuai urutan pendaftarannya.
Console mencatat ketiga langkah secara berurutan untuk setiap request, dan route membaca req.startedAt, property yang ditambahkan oleh logger. Kirim GET /missing: kedua middleware tetap mencatat, karena app.use() cocok dengan setiap path, lalu Express menjawab 404 karena tidak ada route yang cocok.
Lupa next()
Middleware yang tidak mengirim response dan tidak memanggil next() membuat request menggantung. Client menunggu sampai timeout, dan tidak ada yang muncul di log, sehingga ini menjadi bug middleware yang umum. Hapus next(); dari logger di atas lalu kirim GET / lagi: request-nya tidak pernah mendapat jawaban.
Aturannya sederhana: setiap jalur di dalam middleware berakhir dengan tepat satu dari ini:
next()untuk lanjut,next(err)untuk melompat ke error handler (lihat penanganan error Express),- response seperti
res.json()ataures.status(401).send().
Memanggil next() setelah mengirim response juga bug. Handler berikutnya mencoba mengirim response kedua dan Express melempar ERR_HTTP_HEADERS_SENT. Tulis return res.status(401).json(...) supaya fungsinya berhenti di situ.
Cek auth yang menghentikan request
Middleware yang menolak request mengirim response-nya sendiri dan tidak pernah memanggil next(). Berikan sebagai argumen tambahan ke sebuah route untuk melindungi route itu saja:
Request pertama mendapat 401 dengan {"error":"Missing or wrong API key"}. Tambahkan header x-api-key: secret123 di request bar lalu kirim lagi: sekarang jawabannya {"users":42,"caller":"reporting-app"}. /public tidak pernah menjalankan pengecekan itu.
Di mana middleware berjalan
| Kamu menulis | Berjalan untuk |
|---|---|
app.use(fn) | Setiap request, setiap method |
app.use('/api', fn) | Path yang diawali /api |
app.get('/admin', fn, handler) | Hanya GET /admin, sebelum handler |
router.use(fn) | Setiap route di router itu |
Urutan adalah bagian dari maknanya. Logger yang didaftarkan setelah route tidak pernah mencatat request yang dijawab route-route itu, karena route yang mengirim response tidak memanggil next(). Daftarkan dulu middleware untuk seluruh aplikasi seperti logging, parsing body, dan CORS, lalu route-nya, lalu handler 404 dan error.
Middleware bawaan
Express menyertakan beberapa fungsi middleware yang kamu tambahkan dengan app.use(). Parser body mengisi req.body; tanpanya nilainya undefined.
| Middleware | Fungsinya |
|---|---|
express.json() | Mem-parse body JSON (Content-Type: application/json) |
express.urlencoded() | Mem-parse kiriman form HTML (name=Ada&age=36) |
express.text() | Menaruh body teks biasa di req.body sebagai string |
express.static('public') | Menyajikan file dari sebuah folder |
Kirim POST /echo dengan body {"name": "Ada"} dan jawabannya menyertakan "body":{"name":"Ada"}. Hapus baris express.json(), kirim lagi, dan body hilang dari jawaban: req.body bernilai undefined, dan JSON.stringify membuang nilai undefined. Package seperti cors, helmet, dan morgan juga middleware: kamu npm install lalu memberikannya ke app.use() dengan cara yang sama. Halaman express.static membahas cara menyajikan file.
Kesalahan umum
Memanggil middleware alih-alih memberikannya. app.use(logger()) menjalankan logger sekali saat startup dan mendaftarkan nilai kembaliannya. Tulis app.use(logger). (express.json() pakai tanda kurung karena ia mengembalikan fungsi middleware.)
Menambahkan parser body setelah route. Route-nya berjalan lebih dulu dan melihat req.body sebagai undefined.
Mengira app.use('/admin', fn) hanya cocok dengan satu path. Ia juga berjalan untuk /admin/users dan setiap path lain di bawah /admin, untuk setiap method. Untuk menjaga satu route saja, berikan middleware-nya ke app.get('/admin', fn, handler).
Pertanyaan yang sering diajukan
Apa bedanya middleware dan route handler?
Secara teknis tidak ada: keduanya adalah fungsi (req, res, next). Menurut konvensi, route handler mengakhiri request dengan response, sedangkan middleware biasanya mengerjakan tugas bersama lalu memanggil next().
Bisakah middleware async?
Bisa. Di Express 5, middleware async yang melempar error atau mengembalikan promise yang reject otomatis mengirim error-nya ke error handler-mu. Await apa yang kamu butuhkan, lalu panggil next().
Apa yang dilakukan next('route')?
Melewati sisa handler dari route saat ini dan pindah ke route berikutnya yang cocok. Ini hanya bekerja di handler yang ditambahkan dengan app.get(), app.post(), dan fungsi method lainnya, bukan di app.use().
Bagaimana melewati middleware untuk satu route?
Daftarkan route itu sebelum middleware-nya, supaya route itu menjawab lebih dulu, atau cek path-nya di dalam middleware (if (req.path === '/health') return next();). Memasang middleware per router atau per route, bukan untuk seluruh aplikasi, sering membuat hal ini tidak perlu.