Routing di Express — Node.js

Routing menentukan bagaimana aplikasi merespons request ke URL tertentu. Path parameters (:param): // GET /users/42 app.get("/users/:id", (req, res) => {…

Routing adalah cara Express memilih kode mana yang menjawab sebuah request, berdasarkan method dan path-nya. Bayangin resepsionis gedung kantor. Tamu datang dan bilang "mau ke ruang catatan nomor 2". Resepsionis membaca daftar ruangan dari atas, mengantar tamu ke ruangan pertama yang cocok, dan kalau gak ada yang cocok, tamu ditolak di meja depan. Di Express, daftar ruangan itu adalah route-route yang kamu tulis, dan ruangannya adalah function yang menjawab.

🧪 Tebakan cepat: request GET /catatan/2?urut=judul masuk ke route app.get("/catatan/:id", ...). Isi req.params.id apa: angka 2, teks "2", atau "2?urut=judul"? Tebak dulu, jawabannya ada di bagian "Path parameter: req.params".

Route = method + path + handler

Proyek catatan-api kita sekarang punya dua route:

const express = require("express");
const app = express();

const catatan = [
  { id: 1, judul: "Belanja", isi: "beli beras 5 kg" },
  { id: 2, judul: "Belajar", isi: "bab Node.js" },
];

// Semua catatan, bisa disaring dengan ?cari=
app.get("/catatan", (req, res) => {
  const { cari } = req.query;
  if (!cari) return res.json(catatan);
  const hasil = catatan.filter((c) => c.judul.toLowerCase().includes(cari.toLowerCase()));
  res.json(hasil);
});

// Satu catatan berdasarkan id
app.get("/catatan/:id", (req, res) => {
  const item = catatan.find((c) => c.id === Number(req.params.id));
  if (!item) {
    return res.status(404).json({ error: "Catatan tidak ditemukan" });
  }
  res.json(item);
});

app.listen(3000, () => {
  console.log("Server jalan di http://localhost:3000");
});

Path parameter: req.params

:id di path adalah path parameter: tempat kosong yang diisi dari URL. Satu route /catatan/:id melayani /catatan/1, /catatan/2, sampai /catatan/999.

Request Route yang cocok req.params Jawaban
GET /catatan/2 /catatan/:id { id: "2" } {"id":2,"judul":"Belajar","isi":"bab Node.js"}
GET /catatan/2?urut=judul /catatan/:id { id: "2" } sama
GET /catatan/9 /catatan/:id { id: "9" } 404 {"error":"Catatan tidak ditemukan"}

Isi req.params selalu teks, karena URL memang teks. Bagian setelah ? gak ikut ke path, jadi gak ikut ke params. Jawabannya "2", teks. Itu jawaban tebakannya.

Karena teks, "2" === 2 hasilnya false. Makanya route di atas menulis Number(req.params.id) sebelum membandingkan dengan c.id yang berupa angka.

Query string: req.query

Bagian setelah ? adalah query string: pasangan kunci=nilai yang dipisah &. Express menaruhnya di req.query. curl "http://localhost:3000/catatan?cari=jar" mencetak [{"id":2,"judul":"Belajar","isi":"bab Node.js"}].

Kalau gak ada route yang cocok

curl -i http://localhost:3000/halo dijawab HTTP/1.1 404 Not Found dengan halaman HTML kecil bawaan Express yang isinya <pre>Cannot GET /halo</pre>. Method juga dihitung: POST /catatan/2 dijawab Cannot POST /catatan/2, karena kita cuma punya route GET untuk path itu. Bedakan dengan 404 buatan kita sendiri, {"error":"Catatan tidak ditemukan"}: route-nya cocok, tapi datanya gak ada.

Dua hal yang dimaafkan Express: huruf besar kecil (/Catatan/2 tetap cocok) dan garis miring di akhir (/catatan/2/ tetap cocok).

Satu resource, lima route

Pola yang dipakai hampir semua API, namanya REST:

Method Path Untuk
GET /catatan daftar semua catatan
GET /catatan/:id satu catatan
POST /catatan bikin catatan baru
PUT /catatan/:id ubah catatan
DELETE /catatan/:id hapus catatan

Path-nya kata benda (/catatan), aksinya ditentukan method. Tiga yang terakhir kita isi di pelajaran CRUD.

express.Router: route di file sendiri

Kalau route-nya makin banyak, pindahkan ke file sendiri dengan express.Router():

// routes/catatan.js
const express = require("express");
const router = express.Router();

router.get("/", (req, res) => { /* daftar */ });
router.get("/:id", (req, res) => { /* satu catatan */ });

module.exports = router;

// app.js
const catatanRouter = require("./routes/catatan");
app.use("/catatan", catatanRouter);

app.use("/catatan", catatanRouter) menempelkan awalan /catatan ke semua route di router itu. Jadi router.get("/:id") melayani GET /catatan/:id, persis seperti sebelumnya.

📌 Express 5 beda dari tutorial lama

npm install express sekarang memasang Express 5. Banyak tutorial masih Express 4, dan dua pola path-nya bikin Express 5 berhenti waktu start:

Express 4 Express 5 Kalau pola lama dipakai di Express 5
/catatan/:id? /catatan{/:id} PathError [TypeError]: Unexpected ? at index 12: /catatan/:id?; visit https://git.new/pathToRegexpError for info
* /*splat PathError [TypeError]: Missing parameter name at index 1: *; visit https://git.new/pathToRegexpError for info

Di latihan: route tanpa server

Latihannya gak menjalankan server. Fungsi findUser(id) memegang peran handler GET /users/:id: cari di array users dengan find, kembalikan user-nya, atau null kalau gak ada. find mengembalikan undefined kalau gak ketemu, jadi tulis return users.find((u) => u.id === id) || null;. Baris console.log di kode awal yang mencetak hasilnya:

GET /users/2 -> {"id":2,"name":"Siti"}
GET /users/99 -> User not found

⚠️ Jebakan yang sering ketemu

TL;DR: Route = method + path + handler, dicek dari atas, yang pertama cocok yang menjawab. app.get("/catatan/:id", ...) mengisi req.params.id dari URL, selalu sebagai teks ("2", bukan 2), jadi ubah dengan Number() sebelum dibandingkan. Bagian setelah ? masuk ke req.query (?cari=jar jadi { cari: "jar" }) dan gak ikut menentukan route. Gak ada yang cocok: Express menjawab 404 Cannot GET /halo. REST: GET/POST/PUT/DELETE ke /catatan dan /catatan/:id. express.Router() memindahkan route ke file sendiri, dipasang dengan app.use("/catatan", router). Di Express 5, :id? jadi {/:id} dan * jadi /*splat.

Yang akan kamu pelajari