Aplikasi modern jarang bekerja sendirian. Aplikasi mobile mengambil daftar berita dari server lewat API, layanan pembayaran bertukar data dengan bank lewat API, dan panel internal menggabungkan data dari beberapa layanan sekaligus. Ketika dua program dengan bahasa dan platform berbeda perlu berkomunikasi, HTTP menjadi pilihan paling umum karena sudah tersedia di mana saja. Di atas HTTP, gaya arsitektur yang paling banyak dipakai untuk membangun API adalah REST. Pada Chapter ini kita membedah konsep di balik REST — resource, representasi, statelessness, dan uniform interface — sebagai fondasi bagi seluruh Chapter pada Section ini.

REST Adalah Gaya Arsitektur #

REST (REpresentational State Transfer) adalah gaya arsitektur untuk sistem terdistribusi yang diperkenalkan oleh Roy Fielding dalam disertasinya pada tahun 2000; definisi ringkasnya juga tersedia di MDN Web Docs . REST bukan protokol, bukan pustaka, dan bukan framework. REST adalah sekumpulan kendala desain yang diterapkan di atas standar yang sudah ada, yaitu HTTP; sebuah API yang memenuhi kendala-kendala tersebut lazim disebut RESTful. Kendala-kendala tersebut dirangkum pada tabel berikut:

KendalaArtinya bagi API kita
Client-serverAntarmuka pengguna (client) dipisahkan dari penyimpanan data (server) sehingga keduanya dapat berkembang terpisah
StatelessSetiap permintaan berdiri sendiri; server tidak mengingat permintaan sebelumnya saat memproses permintaan berikutnya
CacheResponse diberi penanda yang memungkinkan client atau perantara menyimpannya sementara
Uniform interfaceSemua resource diakses dengan cara seragam: URL untuk mengenali, method untuk bertindak, representasi untuk bertukar data
Layered systemClient tidak perlu tahu apakah komunikasi sampai langsung ke server atau melewati load balancer, proxy, dan cache

Satu kendala opsional lain bernama code on demand memperbolehkan server mengirim kode yang dieksekusi client, tetapi kendala ini jarang dipakai API modern. Dari lima kendala pada tabel, dua yang paling memengaruhi cara kita menulis kode Node.js adalah stateless dan uniform interface; keduanya dibedah di penghujung Chapter ini.

Resource dan Penamaannya #

Inti dari REST adalah resource: setiap “benda” yang layak diberi identitas, misalnya satu tugas, satu pengguna, atau satu artikel. Setiap resource diidentifikasi lewat URL, dan kualitas sebuah REST API sangat ditentukan oleh kualitas penamaan URL tersebut. Aturan utamanya: URL menyebut kata benda jamak, bukan kata kerja, karena aksi sudah menjadi tugas method HTTP.

Pola kurang tepatPola RESTfulAlasan
GET /ambilDaftarTugasGET /tugasKata kerja tidak perlu; GET pada koleksi sudah berarti “ambil daftar”
POST /tugas/baruPOST /tugasPOST pada koleksi memang berarti “buat item baru”
GET /hapusTugas/42DELETE /tugas/42Penghapusan adalah peran method DELETE, bukan bagian dari URL
GET /tugas?id=42GET /tugas/42Satu item adalah resource tersendiri, bukan saringan pada koleksi

Gaya seperti GET /ambilDaftarTugas adalah warisan pola RPC (Remote Procedure Call): URL berisi nama prosedur yang dipanggil. REST membalik cara pandang tersebut — URL menyebut benda yang dituju, method menyebut apa yang dilakukan terhadap benda tersebut. Hasilnya, sekali pembaca memahami bahwa koleksi tugas berada di /tugas, pembaca bisa menebak tanpa dokumentasi bahwa detail tugas nomor 42 berada di /tugas/42 dan komentarnya di /tugas/42/komentar.

Method HTTP sebagai Kata Kerja #

Jika URL adalah kata benda, method HTTP adalah kata kerja yang melengkapinya. GET membaca representasi resource, POST membuat resource baru pada koleksi, PUT mengganti isi resource, PATCH mengubah sebagian isi, dan DELETE menghapusnya — daftar lengkapnya ada di dokumentasi HTTP method MDN . Kombinasi method dan URL membentuk kalimat yang utuh: DELETE /tugas/42 berarti “hapus tugas nomor 42”. Dari lima method tersebut, GET bersifat safe — tidak pernah mengubah data di server — sehingga browser dan cache berani memanggilnya berulang kali. Tabel lengkap beserta kolom idempotency menanti pada Chapter Merancang Endpoint REST.

Representasi: Bentuk Data yang Ditukar #

Client tidak pernah mengolah resource secara langsung; yang dikirim dan diterima adalah representasi — data yang menggambarkan kondisi resource pada suatu saat. Format representasi paling umum saat ini adalah JSON dengan header Content-Type: application/json, meskipun secara teori resource yang sama juga bisa diwakili format lain seperti XML. Server kita akan selalu mengirim JSON. Mari kita lihat ketiga sifat tersebut — resource, method, dan representasi — bekerja dalam satu server kecil yang dibangun dengan modul node:http :

js
import http from 'node:http';

const host = '127.0.0.1';
const tugas = [
  { id: 1, title: 'Belajar Node.js', status: 'selesai' },
  { id: 2, title: 'Menulis dokumentasi API', status: 'belum' },
];

function kirimJson(res, kode, data) {
  res.writeHead(kode, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(data));
}

const server = http.createServer((req, res) => {
  const url = new URL(req.url, `http://${host}`);

  if (req.method === 'GET' && url.pathname === '/tugas') {
    return kirimJson(res, 200, tugas);
  }
  if (req.method === 'GET' && url.pathname === '/tugas/1') {
    return kirimJson(res, 200, tugas[0]);
  }
  return kirimJson(res, 404, {
    error: { kode: 'TIDAK_ADA', pesan: 'Endpoint tidak ditemukan' },
  });
});

server.listen(0, host, async () => {
  const port = server.address().port;

  const koleksi = await fetch(`http://${host}:${port}/tugas`);
  console.log(koleksi.status, koleksi.headers.get('content-type'));
  console.log(JSON.stringify(await koleksi.json()));

  const satu = await fetch(`http://${host}:${port}/tugas/1`);
  console.log(satu.status, JSON.stringify(await satu.json()));

  const tidakAda = await fetch(`http://${host}:${port}/tugas/99`);
  console.log(tidakAda.status, JSON.stringify(await tidakAda.json()));

  server.close();
  server.closeAllConnections();
});

Output yang Dihasilkan:

text
200 application/json
[{"id":1,"title":"Belajar Node.js","status":"selesai"},{"id":2,"title":"Menulis dokumentasi API","status":"belum"}]
200 {"id":1,"title":"Belajar Node.js","status":"selesai"}
404 {"error":{"kode":"TIDAK_ADA","pesan":"Endpoint tidak ditemukan"}}

Kode di atas memakai pola server + fetch yang sudah kita kenal dari Section HTTP dan Web Servers: server mendengarkan port acak (listen(0)), client memanggil beberapa endpoint, lalu server ditutup agar proses keluar. Output sengaja hanya mencetak status dan body, bukan seluruh header, karena header seperti date berubah setiap detik. Mari kita telaah bagian-bagiannya:

  1. Baris 3-7 (const host dan const tugas): Alamat host disimpan satu kali agar mudah dipakai ulang, dan dua resource tugas disimpan sebagai array object. Field memakai nama Inggris (title, status) mengikuti kebiasaan industri, sementara nilainya berbahasa Indonesia — konvensi yang kita pakai konsisten di seluruh Section ini.
  2. Baris 9-12 (function kirimJson(...)): Helper ini mengirim representasi JSON sekaligus menetapkan header Content-Type: application/json, sehingga client tahu cara membaca body response.
  3. Baris 15 (new URL(req.url, ...)): Class URL mengurai alamat permintaan menjadi pathname dan query parameter — alat yang akan sering kita pakai pada Chapter Pagination dan Filtering.
  4. Baris 17-22 (dua cabang GET): Route /tugas mengembalikan representasi koleksi (array), sedangkan /tugas/1 mengembalikan representasi satu item (object). Keduanya adalah resource berbeda dengan URL berbeda.
  5. Baris 23-26 (fallback 404): Permintaan ke resource yang tidak ada dijawab status 404 dengan body JSON berbentuk seragam — bentuk error ini kita formalkan pada Chapter Status Code dan Penanganan Error.
  6. Baris 28-39 (listen dan tiga pemanggilan fetch): Server mendengarkan port acak lewat listen(0), lalu client memanggil tiga endpoint secara berurutan. Setiap permintaan berdiri sendiri — hanya method dan URL yang menentukan hasilnya, tanpa keadaan tersembunyi apa pun. Pemanggilan close() dan closeAllConnections() di penghujung callback memastikan proses Node.js berhenti begitu demo selesai.

Stateless: Setiap Permintaan Berdiri Sendiri #

Kendala stateless sering disalahpahami, jadi mari kita tepiskan dua hal. Pertama, stateless tidak berarti API tidak boleh memiliki data; penyimpanan tetap berada di server — yang dilarang adalah server mengingat permintaan sebelumnya untuk memproses permintaan berikutnya. Kedua, stateless bukan berarti client tidak punya sesi login; sesi cukup diwakili token yang dikirim ulang pada setiap permintaan lewat header, bukan rekam jejak di memori server.

Keuntungan praktisnya besar: server mana pun dalam kluster bisa melayani permintaan mana pun, satu permintaan bisa dianalisis sendiri saat menelusuri masalah, dan percobaan ulang permintaan idempoten tidak menimbulkan efek ganda. Pola autentikasi berbasis token yang cocok dengan kendala ini dibahas pada Section Authentication dan Authorization.

Dengan resource, method, representasi, dan statelessness sebagai bekal, kita siap beranjak dari konsep ke praktik: Chapter Merancang Endpoint REST menyusun aturan URL, tabel method, dan konvensi status code menjadi rancangan API yang utuh.