Menguasai routing Express: route methods GET POST PUT dan DELETE, path parameters, query string, route patterns, app.route, serta membangun REST routing yang benar dan bersih.

Setelah di episode 3 server Hello World kalian berjalan, episode 4 membahas bagian yang paling sering dipakai sehari-hari: routing — cara aplikasi memetakan kombinasi URL dan metode HTTP ke handler tertentu.
Mengapa routing adalah fondasi penting? Karena setiap API pada dasarnya adalah kumpulan keputusan: "ketika client meminta GET /users/42, jalankan logika ini". Routing yang tertata berarti API yang mudah diprediksi, mudah diuji, dan mudah didokumentasikan. Kesalahan routing (misalnya handler yang tidak pernah terpanggil karena tertimpa route lain) adalah bug yang paling sering menimpa developer Express pemula.
Express menyediakan metode yang mencerminkan metode HTTP. Sintaksnya konsisten: app.<method>(path, handler).
app.get("/users", (req, res) => {
res.json({ data: [] })
})
app.post("/users", (req, res) => {
res.status(201).json({ message: "User dibuat" })
})
app.put("/users/:id", (req, res) => {
res.json({ message: `User ${req.params.id} diperbarui` })
})
app.delete("/users/:id", (req, res) => {
res.json({ message: `User ${req.params.id} dihapus` })
})Satu path bisa melayani banyak metode. Express juga punya app.all(path, handler) yang menjalankan handler untuk semua metode HTTP — berguna untuk middleware per-path atau fallback.
Path parameter ditandai dengan :nama:
app.get("/users/:id", (req, res) => {
res.json({ id: req.params.id })
})Request GET /users/42 akan mengisi req.params.id dengan string "42". Perhatikan dua hal:
req.params.id berisi "42" bukan angka 42. Konversi ke number harus eksplisit (Number(...)), biasanya setelah validasi (episode 13)./files/:folder/:name menghasilkan req.params.folder dan req.params.name.Gunakan ? untuk membuat segmen opsional (Express 5 mendukung sintaks ini):
app.get("/users/:id?/:page?", (req, res) => {
res.json(req.params)
})GET /users menghasilkan req.params kosong, sedangkan GET /users/42/3 mengisi keduanya.
Data yang tidak layak menjadi bagian dari URL (filter, pagination, pencarian) dikirim lewat query string dan tersedia di req.query:
app.get("/users", (req, res) => {
const { page = "1", limit = "10", role } = req.query
res.json({ page, limit, role })
})GET /users?page=2&limit=20&role=admin menghasilkan req.query sebagai objek { page: "2", limit: "20", role: "admin" }. Seperti path parameter, semua nilai query adalah string — pola parsing dan validasi yang benar dibahas di episode 23 (pagination) dan episode 13 (validasi).
Selain string literal dan parameter, Express mendukung pola regex:
app.get("/users/:id(\\d+)", (req, res) => {
res.json({ numericId: req.params.id })
})
app.get(/\/files\/(.*)/, (req, res) => {
res.json({ rest: req.params[0] })
})/users/:id(\\d+) hanya cocok untuk :id yang semuanya digit — GET /users/abc tidak akan memicu route ini. Ini cara bersih untuk memisahkan validasi bentuk URL dari logika handler.
Ketika satu resource punya banyak metode, app.route() meringkasnya dalam satu blok yang mudah dibaca:
app
.route("/users/:id")
.get((req, res) => {
res.json({ id: req.params.id })
})
.put((req, res) => {
res.json({ updated: req.params.id })
})
.delete((req, res) => {
res.json({ deleted: req.params.id })
})Keunggulannya: path ditulis sekali, sehingga tidak ada risiko typo antar metode. Ini juga titik awal yang baik menuju express.Router() di episode 8.
Important
Express mengevaluasi route secara berurutan sesuai urutan pendaftaran dan memakai yang pertama cocok. Route spesifik (/users/:id) harus didaftarkan sebelum route generik yang bisa menelan request serupa (/users/me → pastikan :id tidak dipakai sebagai path param untuk nama khusus, atau daftarkan yang literal lebih dulu).
Dengan pola di atas, sekumpulan route REST lengkap untuk resource users:
| Metode | Path | Fungsi |
|---|---|---|
| GET | /users | List user (dengan query pagination) |
| GET | /users/:id | Detail satu user |
| POST | /users | Buat user baru |
| PUT | /users/:id | Perbarui seluruh data user |
| PATCH | /users/:id | Perbarui sebagian data user |
| DELETE | /users/:id | Hapus user |
Perbedaan PUT vs PATCH penting: PUT mengganti seluruh resource, PATCH hanya bidang tertentu. Mengikuti konvensi ini membuat API kalian bisa diprediksi oleh konsumen.
Membandingkan req.params.id === 42 selalu false. Konversi tipe dengan eksplisit — dan lakukan di layer validasi, bukan asal di handler.
Route yang didaftarkan lebih awal menang. Daftarkan route literal/spesifik sebelum route parameter agar tidak saling menutup.
Tip
Uji setiap route dengan curl sambil membaca req.params dan req.query lewat res.json(req.params) — cara tercepat untuk melihat apa yang sebenarnya diterima Express dari URL.
Episode 4 membekali kalian seluruh perangkat routing Express: route methods, path parameters dengan parameter opsional, query string, route pattern regex, dan app.route() untuk merapikan banyak metode pada satu resource.
Inti yang harus dibawa pulang:
app.get/post/put/patch/delete.:id) selalu berupa string; konversi tipe dilakukan eksplisit.req.query — tempat filter dan pagination.app.route() menggabungkan banyak metode pada satu path.Di episode 5 selanjutnya kita akan membahas middleware dasar — built-in seperti express.json, urlencoded, dan static, third-party seperti cors dan morgan, serta cara menulis custom middleware untuk logging dan parsing. Sampai jumpa di episode 5!