- Bab 5 dari 9
- 25 menit
- 4 soal kuis
Membangun REST API
Di bab ini (6 bagian)
Tujuan bab ini
Dalam bab ini, kamu akan mempelajari cara membangun sebuah REST API yang solid dan sesuai standar industri. Tujuan utama kita mencakup:
- Menerapkan konvensi REST dan status code yang tepat.
- Membuat operasi CRUD (Create, Read, Update, Delete) yang lengkap.
- Menyusun struktur folder proyek yang rapi dan mudah dirawat.
Konvensi REST dan Status Code
REST (Representational State Transfer) adalah gaya arsitektur standar untuk merancang API. Saat membangun REST API, kita berinteraksi dengan sebuah "resource" atau sumber daya. Praktik terbaik menyarankan penggunaan kata benda jamak untuk menamai resource tersebut, misalnya /api/users bukan /api/user atau /api/getUser.
Aksi yang dilakukan pada resource tersebut ditentukan oleh metode HTTP yang digunakan. Ini membuat URL kita tetap bersih dan mudah diprediksi.
Berikut adalah pemetaan metode HTTP dan fungsinya:
- GET: Digunakan untuk membaca data. Contoh:
GET /api/usersuntuk mengambil daftar semua pengguna, atauGET /api/users/:iduntuk melihat detail satu pengguna secara spesifik. - POST: Digunakan untuk membuat data baru. Contoh:
POST /api/usersakan membuat pengguna baru. - PUT / PATCH: Keduanya digunakan untuk memperbarui data. Biasanya
PUTuntuk mengganti seluruh data resource, sedangkanPATCHuntuk mengubah sebagian data saja. Contoh:PATCH /api/users/:id. - DELETE: Digunakan untuk menghapus data. Contoh:
DELETE /api/users/:id.
Selain metode, API yang baik juga harus mengembalikan HTTP status code yang tepat agar klien (seperti aplikasi frontend atau mobile) mengerti apa yang terjadi dengan permintaan mereka.
- 200 OK: Permintaan berhasil. Biasanya untuk GET, PUT, atau PATCH.
- 201 Created: Resource baru berhasil dibuat. Ini adalah respons standar untuk POST yang sukses.
- 204 No Content: Permintaan berhasil, tetapi tidak ada data yang perlu dikembalikan. Sangat cocok untuk DELETE yang sukses.
- 400 Bad Request: Permintaan klien tidak valid, misalnya format data salah.
- 401 Unauthorized: Klien belum terautentikasi atau gagal login.
- 403 Forbidden: Klien sudah login, tetapi tidak memiliki izin (hak akses) untuk melakukan tindakan tersebut.
- 404 Not Found: Resource yang diminta tidak ada.
- 500 Server Error: Terjadi kesalahan internal di sisi server kita.
Kesalahan umum di sini adalah mengembalikan status 200 OK untuk segala jenis respons, bahkan ketika terjadi error, dan hanya menyelipkan pesan error di dalam body JSON. Hal ini menyalahi konvensi REST dan membuat klien kesulitan mendeteksi error secara otomatis.
Membuat Operasi CRUD Lengkap
Sekarang mari kita terapkan konvensi di atas ke dalam kode. Kita akan membuat operasi CRUD dasar menggunakan array sederhana di memori untuk menyimpan data. Tentu saja pada aplikasi nyata, kamu akan menggunakan database.
Dalam contoh di atas, perhatikan bagaimana kita secara konsisten menggunakan pengecekan if (!user) lalu membalas dengan res.sendStatus(404) jika resource tidak ada. Untuk POST, kita secara eksplisit menggunakan res.status(201).json(user). Pada DELETE, fungsi res.sendStatus(204) digunakan karena tidak ada data spesifik yang perlu ditampilkan ulang setelah objek terhapus.
Validasi Input dari Klien
Aturan emas dalam pengembangan server web adalah jangan pernah percaya pada input dari klien. Semua data yang masuk dari luar harus divalidasi dengan ketat sebelum diproses atau disimpan ke database.
Kita bisa menggunakan pustaka pihak ketiga seperti Zod, Joi, atau express-validator untuk mendefinisikan skema data yang valid. Zod cukup populer karena integrasinya yang baik dengan TypeScript. Kita bisa membuat sebuah middleware reusable bernama validate() untuk memvalidasi body request pada route mana pun.
Berikut adalah contoh penerapan validasi dengan Zod:
Pada kode validasi di atas, jika req.body tidak lolos uji (misalnya nama terlalu pendek, atau email tidak valid formatnya), middleware akan langsung menghentikan proses request dan mengembalikan status code 422 (Unprocessable Entity) beserta daftar error result.error.issues. Jika validasi berhasil, fungsi next() dipanggil agar eksekusi berlanjut ke handler utama.
Menyusun Struktur Folder Proyek
Seiring dengan bertambah besarnya kode aplikasimu, meletakkan semua route dan logika bisnis di dalam satu file app.js akan menjadi sangat tidak efisien dan sulit dipelihara. Express tidak memaksakan struktur spesifik, tetapi ada konvensi umum yang banyak digunakan oleh komunitas.
Struktur yang baik memisahkan kode berdasarkan tanggung jawab (separation of concerns). Berikut gambaran struktur folder standar yang disarankan:
src/app.js: File ini bertanggung jawab untuk konfigurasi awal Express.src/server.js: Menjalankan fungsiapp.listen()untuk memulai server.src/routes/: Menyimpan file-file yang memetakan URL dan metode HTTP ke controller yang tepat.src/controllers/: Tempat logika request dan response berada. Controller membaca input (req), memanggil fungsi dari service, dan mengirim hasil (res).src/services/: Tempat bersemayamnya logika bisnis inti. Sebisa mungkin, kode di layer ini tidak bergantung secara langsung pada Express (tidak adareqataures), sehingga mudah dites ulang atau dipindahkan.src/models/: Berisi kode untuk berinteraksi dengan database atau konfigurasi ORM.src/middleware/: Tempat menyimpan middleware kustom seperti autentikasi (auth), validasi input, atau penanganan error (error handler).src/config/: Menyimpan konfigurasi aplikasi atau database.src/tests/: Tempat menyimpan skrip pengujian atau unit test.
Pemisahan fungsi secara spesifik ke dalam routes, controllers, dan services memberikan fleksibilitas tinggi. Misalnya, bila nanti kamu ingin menambahkan akses API melalui pesan antrean (message queue) di samping HTTP, logika bisnismu yang ada di folder services tetap utuh dan bisa langsung digunakan kembali tanpa perlu menulis ulang.
Rangkuman
- Gunakan nama resource dalam bentuk jamak dan terapkan aksi menggunakan metode HTTP yang relevan seperti GET, POST, PUT/PATCH, dan DELETE.
- Pastikan respons selalu mengembalikan status code yang akurat untuk setiap aksi CRUD, seperti 201 untuk Create dan 204 untuk aksi Delete.
- Semua input yang diterima dari klien tidak boleh langsung dipercaya dan wajib melewati tahapan validasi sebelum diproses lebih lanjut.
- Organisasikan kodemu ke dalam layer yang terpisah dengan membagi tanggung jawab fungsi ke dalam folder spesifik seperti
routes,controllers, danservices.
Selesaikan bab ini
- 1. Baca materi
- 2. Kuis (4 soal)
Cek pemahaman
1Metode HTTP dan status code mana yang direkomendasikan untuk membuat data resource baru pada REST API?
2Berdasarkan potongan kode handler Express berikut, status code apa yang paling tepat untuk mengisi bagian yang kosong (titik-titik) ketika resource sukses dihapus?
app.delete('/api/users/:id', (req, res) => { const user = find(req.params.id); if (!user) return res.sendStatus(404); const index = users.indexOf(user); users.splice(index, 1); res.sendStatus(...); });3Berdasarkan konvensi struktur folder aplikasi, file controller di dalam folder `src/controllers/` sebaiknya berisikan logika bisnis mandiri yang terbebas dari campur tangan fungsi spesifik Express.
4Jika kamu menggunakan skema Zod dan menemukan bahwa input dari request body tidak sesuai (misal email salah format), status code apa yang idealnya kamu kembalikan melalui blok middleware validasi?