Dalam pengembangan web modern, Representational State Transfer (REST) API telah menjadi standar de facto untuk membangun layanan web yang skalabel, mudah dikelola, dan mudah dipahami. Inti dari setiap RESTful API terletak pada konsep fundamental: sumber daya (resource). Memahami apa itu sumber daya, bagaimana mereka diidentifikasi, dan bagaimana kita berinteraksi dengannya sangat penting untuk merancang dan menggunakan REST API secara efektif. Artikel ini akan menggali lebih dalam sifat sumber daya dalam REST API, menjelajahi karakteristiknya, hubungannya dengan koleksi, dan operasi umum yang dilakukan padanya.
Ide inti di balik REST adalah bahwa API mengekspos sekumpulan sumber daya, dan klien berinteraksi dengan sumber daya ini dengan mengirimkan permintaan ke pengidentifikasi uniknya. Tapi apa sebenarnya yang merupakan "sumber daya"? Dalam konteks REST API, sumber daya bisa berupa hampir apa pun yang bisa Anda beri nama. Itu bisa berupa entitas nyata seperti pelanggan, produk, atau pesanan. Itu juga bisa berupa konsep abstrak seperti layanan, transaksi, atau perhitungan. Kuncinya adalah bahwa itu adalah item yang menarik yang dapat diidentifikasi dan dimanipulasi.
Anggaplah internet itu sendiri sebagai koleksi sumber daya yang luas. Setiap halaman web, gambar, video, atau dokumen yang Anda akses secara online adalah sumber daya, masing-masing dengan alamat uniknya sendiri (URL). REST API mengadopsi filosofi yang sama ini. Baik itu profil pengguna di platform media sosial, buku tertentu di perpustakaan online, atau ramalan cuaca untuk kota tertentu, masing-masing adalah sumber daya yang disediakan oleh API.
Ingin platform Terintegrasi, All-in-One untuk Tim Pengembang Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
Mengidentifikasi Sumber Daya: Peran URI
Sangat penting, setiap sumber daya dalam REST API harus memiliki setidaknya satu pengidentifikasi unik. Pengidentifikasi ini biasanya adalah Uniform Resource Identifier (URI). Bentuk URI yang paling umum digunakan dalam web API adalah Uniform Resource Locator (URL), yang tidak hanya mengidentifikasi sumber daya tetapi juga menyediakan cara untuk menemukannya.
Misalnya, dalam API untuk mengelola blog, posting blog tertentu dapat diidentifikasi oleh URI seperti /posts/123
. Di sini, /posts
kemungkinan mewakili koleksi posting, dan 123
adalah pengidentifikasi unik untuk posting tertentu dalam koleksi itu. Demikian pula, sumber daya pengguna dapat diidentifikasi oleh /users/john.doe
.
Desain URI ini adalah aspek penting dari desain API. URI yang dirancang dengan baik bersifat intuitif, dapat diprediksi, dan mudah dipahami serta digunakan oleh pengembang. Mereka harus bertindak sebagai penunjuk yang jelas, menunjukkan sifat sumber daya yang diakses. Praktik yang baik menentukan penggunaan kata benda untuk mewakili sumber daya (misalnya, /products
, /orders
) daripada kata kerja (misalnya, /getProducts
, /createOrder
). Metode HTTP (GET, POST, PUT, DELETE) kemudian digunakan untuk menentukan tindakan yang akan dilakukan pada sumber daya yang diidentifikasi oleh URI.
Sumber Daya vs. Representasi: Perbedaan Kunci
Penting untuk memahami perbedaan antara sumber daya dan representasinya. Sumber daya adalah entitas konseptual itu sendiri – "benda" yang sebenarnya (pelanggan, produk, ide). Representasi, di sisi lain, adalah cuplikan dari keadaan sumber daya tersebut pada titik waktu tertentu, biasanya diformat dalam tipe media tertentu seperti JSON (JavaScript Object Notation) atau XML (eXetensible Markup Language).
Ketika klien meminta sumber daya dari API, ia tidak menerima sumber daya itu sendiri (yang merupakan konsep abstrak yang berada di server). Sebaliknya, ia menerima representasi dari sumber daya tersebut. Misalnya, jika Anda meminta /users/jane.doe
, API mungkin mengembalikan representasi JSON seperti:JSON
{
"id": "jane.doe",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"dateJoined": "2023-01-15T10:00:00Z"
}
Objek JSON ini bukanlah Jane Doe itu sendiri; ini adalah representasi dari datanya sebagaimana disimpan oleh sistem. Sumber daya yang sama berpotensi memiliki banyak representasi. Misalnya, API mungkin juga mampu menyediakan representasi XML dari pengguna yang sama jika diminta oleh klien melalui negosiasi konten (menggunakan header HTTP seperti Accept
).
Keadaan sumber daya dapat berubah seiring waktu. Jika Jane Doe memperbarui alamat emailnya, sumber daya pengguna yang mendasarinya berubah. Permintaan selanjutnya untuk /users/jane.doe
kemudian akan mengembalikan representasi baru yang mencerminkan keadaan yang diperbarui ini. Di sinilah bagian "State Transfer" dari REST berperan: klien berinteraksi dengan sumber daya dengan mengambil dan memanipulasi keadaannya melalui representasi ini.
Koleksi: Sumber Daya yang Mengandung Sumber Daya Lain
Seringkali, sumber daya dikelompokkan menjadi koleksi. Koleksi itu sendiri adalah sumber daya. Misalnya, /posts
dalam API blog kita adalah sumber daya koleksi yang berisi sumber daya posting individu. Demikian pula, /users
akan menjadi koleksi sumber daya pengguna.
Ketika klien mengirim permintaan GET ke URI koleksi seperti /products
, API biasanya mengembalikan representasi yang mencantumkan sumber daya anggota dalam koleksi itu, seringkali dengan beberapa informasi ringkasan untuk masing-masing. Daftar ini mungkin terlihat seperti ini:JSON
[
{
"id": "prod_abc",
"name": "Laptop Pro 15",
"price": 1299.99,
"link": "/products/prod_abc"
},
{
"id": "prod_xyz",
"name": "Wireless Mouse Ergonomic",
"price": 39.99,
"link": "/products/prod_xyz"
},
// ... produk lainnya
]
Perhatikan bagaimana setiap item dalam koleksi seringkali menyertakan tautan (atau URI-nya sendiri) ke sumber daya individu, memungkinkan klien untuk menavigasi dan mengambil detail lengkap produk tertentu jika diperlukan.
Merancang URI untuk koleksi dan anggotanya mengikuti pola logis. Biasanya:
/resources
mengacu pada koleksi (misalnya,/orders
)./resources/{id}
mengacu pada anggota tertentu dalam koleksi itu (misalnya,/orders/567
).
Struktur hierarkis ini membuat API intuitif dan selaras dengan hubungan konseptual antara koleksi dan elemen-elemennya.
Operasi pada Sumber Daya dan Koleksi
Interaksi dengan sumber daya dan koleksi dalam REST API dicapai melalui metode HTTP standar. Metode-metode ini menentukan tindakan yang akan dilakukan. Metode yang paling umum adalah:
GET: Digunakan untuk mengambil representasi sumber daya atau koleksi.
GET /posts
akan mengambil daftar semua posting (koleksi).GET /posts/123
akan mengambil posting spesifik dengan ID 123. Permintaan GET harus aman (safe), artinya tidak boleh memiliki efek samping pada server; mereka murni untuk mengambil data. Mereka juga harus idempoten (idempotent), artinya beberapa permintaan GET yang identik harus memiliki efek yang sama dengan satu permintaan (yaitu, mengembalikan representasi yang sama, dengan asumsi sumber daya belum berubah sementara itu).
POST: Terutama digunakan untuk membuat sumber daya baru dalam koleksi. Badan permintaan (request body) biasanya berisi representasi sumber daya baru yang akan dibuat.
POST /posts
dengan badan permintaan yang berisi detail posting blog baru (misalnya, judul, konten, penulis) akan menginstruksikan server untuk membuat posting baru itu. Server biasanya merespons dengan status201 Created
dan seringkali menyertakan URI sumber daya yang baru dibuat di headerLocation
dari respons. Permintaan POST umumnya tidak aman (karena membuat sumber daya baru) dan tidak idempoten (beberapa permintaan POST yang identik biasanya akan membuat beberapa sumber daya baru). POST juga dapat digunakan untuk operasi non-idempoten lainnya yang tidak sesuai dengan metode HTTP lainnya, seperti memicu proses atau mengirim data untuk diproses di mana hasilnya bukan hanya pembaruan pada sumber daya teridentifikasi yang ada.
PUT: Digunakan untuk memperbarui sumber daya yang ada sepenuhnya. Badan permintaan harus berisi representasi baru lengkap dari sumber daya. Jika sumber daya yang diidentifikasi oleh URI ada, ia diganti dengan representasi baru. Jika tidak ada, beberapa API mungkin memilih untuk membuatnya (meskipun perilaku ini dapat bervariasi).
PUT /posts/123
dengan badan permintaan yang berisi judul dan konten yang diperbarui untuk posting 123 akan mengganti posting 123 yang ada dengan data baru. Permintaan PUT tidak aman (karena memodifikasi sumber daya) tetapi idempoten. Mengirim permintaan PUT yang sama beberapa kali akan menghasilkan keadaan yang sama untuk sumber daya. Misalnya, memperbarui judul posting menjadi "Judul Baru" beberapa kali masih menghasilkan judul menjadi "Judul Baru".
DELETE: Digunakan untuk menghapus sumber daya.
DELETE /posts/123
akan menghapus posting blog dengan ID 123. Permintaan DELETE tidak aman (mereka menghapus data) tetapi idempoten. Menghapus sumber daya beberapa kali harus memiliki hasil yang sama dengan menghapusnya sekali (sumber daya hilang). Permintaan DELETE selanjutnya ke URI yang sama mungkin mengembalikan404 Not Found
atau204 No Content
.
PATCH: Digunakan untuk memperbarui sebagian sumber daya yang ada. Berbeda dengan PUT, yang mengharuskan klien untuk mengirim seluruh representasi sumber daya, PATCH memungkinkan pengiriman hanya perubahan. Misalnya, untuk memperbarui hanya alamat email pengguna, permintaan PATCH hanya perlu menyertakan email baru.
PATCH /users/jane.doe
dengan badan permintaan seperti{"email": "new.email@example.com"}
hanya akan memperbarui alamat email Jane, membiarkan bidang lain seperti namanya tidak berubah. Permintaan PATCH tidak aman. Idempotensinya dapat diperdebatkan dan tergantung pada sifat operasi patch. Misalnya, operasi PATCH yang mengatakan "tambahkan '!' ke deskripsi" tidak idempoten, sedangkan "atur deskripsi menjadi 'nilai baru'" adalah idempoten.
Sumber Daya Tunggal (Singleton Resources)
Meskipun koleksi dan anggotanya umum, terkadang sumber daya adalah entitas mandiri, sering disebut sebagai sumber daya "tunggal". Contoh yang baik mungkin adalah konfigurasi aplikasi tertentu atau status sistem saat ini.
Misalnya, /application/configuration
bisa menjadi URI untuk sumber daya tunggal yang mewakili pengaturan konfigurasi aplikasi. Permintaan GET
ke URI ini akan mengambil konfigurasi saat ini, dan permintaan PUT
dapat digunakan untuk memperbaruinya. Tidak ada "koleksi" konfigurasi dalam konteks ini; hanya ada konfigurasi.
Demikian pula, /system/status
dapat mewakili status operasional sistem saat ini.
Praktik Terbaik untuk Merancang API Berbasis Sumber Daya
Merancang API yang berpusat pada sumber daya melibatkan lebih dari sekadar mengidentifikasi entitas dan memetakannya ke URI. Beberapa praktik terbaik berkontribusi pada API yang kuat dan ramah pengguna:
- Gunakan Kata Benda untuk URI: Seperti disebutkan sebelumnya, URI sumber daya harus berupa kata benda (misalnya,
/products
,/users/{userId}/orders
). Kata kerja harus dicadangkan untuk metode HTTP. - Penamaan URI yang Konsisten: Gunakan konvensi penamaan yang konsisten untuk URI Anda. Kata benda jamak umumnya lebih disukai untuk koleksi (misalnya,
/customers
daripada/customer
). Gunakan tanda hubung (-
) untuk meningkatkan keterbacaan segmen jalur yang panjang (misalnya,/product-categories
) daripada garis bawah (_
) atau camelCase. - Jaga URI Tetap Sederhana dan Hierarkis: Rancang URI yang mencerminkan hubungan antar sumber daya. Misalnya,
/users/{userId}/accounts/{accountId}
dengan jelas menunjukkan bahwa akun milik pengguna. Namun, hindari penyarangan yang terlalu dalam, yang dapat membuat URI menjadi sulit diatur. - Tanpa Status (Statelessness): Setiap permintaan dari klien ke server harus berisi semua informasi yang diperlukan untuk memahami1 dan memproses permintaan. Server2 tidak boleh menyimpan konteks klien apa pun di antara permintaan. Ini adalah prinsip inti dari REST dan berkontribusi pada skalabilitas.
- Manfaatkan Metode HTTP dengan Benar: Gunakan GET, POST, PUT, DELETE, dan PATCH sesuai dengan semantik yang ditentukan. Jangan gunakan GET untuk memodifikasi data atau POST untuk mengambil data ketika GET lebih tepat.
- Gunakan Kode Status HTTP dengan Tepat: Kembalikan kode status HTTP standar untuk menunjukkan hasil permintaan (misalnya,
200 OK
,201 Created
,204 No Content
,400 Bad Request
,401 Unauthorized
,403 Forbidden
,3404 Not Found
,500 Internal Server Error
). Ini memberikan umpan balik yang jelas kepada klien. - Dukung Negosiasi Konten: Izinkan klien untuk menentukan format representasi yang diinginkan (misalnya, JSON, XML) menggunakan header
Accept
dan menunjukkan format badan permintaan menggunakan headerContent-Type
. - Versi (Versioning): Rencanakan evolusi API dengan mengimplementasikan strategi versi (misalnya,
/v1/products
). Ini memungkinkan Anda untuk memperkenalkan perubahan yang merusak tanpa memengaruhi klien yang sudah ada. - Sediakan Representasi Kesalahan yang Bermakna: Ketika terjadi kesalahan, kembalikan pesan kesalahan yang berguna di badan respons (biasanya JSON atau XML) yang menjelaskan apa yang salah.
- Hypermedia as the Engine of Application State (HATEOAS): Meskipun tidak selalu sepenuhnya diimplementasikan, HATEOAS adalah prinsip kunci REST. Ini berarti bahwa representasi sumber daya harus menyertakan tautan (kontrol hypermedia) yang memungkinkan klien untuk menemukan tindakan dan sumber daya terkait. Misalnya, representasi pesanan mungkin menyertakan tautan untuk membatalkan pesanan, melihat status pengirimannya, atau melihat produk yang dikandungnya. Ini membuat API lebih mudah ditemukan sendiri.
Granularitas Sumber Daya
Salah satu tantangan desain umum adalah menentukan granularitas yang tepat dari sumber daya Anda. Haruskah alamat menjadi sumber daya terpisah, atau bagian dari sumber daya pengguna? Haruskah item pesanan menjadi sumber daya yang berbeda, atau disematkan dalam sumber daya pesanan?
Tidak ada satu jawaban yang benar; itu tergantung pada kasus penggunaan spesifik dan bagaimana klien biasanya akan berinteraksi dengan data.
- Sumber Daya Terpisah: Jika suatu entitas (seperti alamat) dapat dibuat, diambil, diperbarui, atau dihapus secara independen, atau jika dibagi di antara beberapa sumber daya lain, seringkali masuk akal untuk memodelkannya sebagai sumber daya terpisah dengan URI-nya sendiri (misalnya,
/addresses/{addressId}
). Anda kemudian dapat menautkannya dari sumber daya lain (misalnya, sumber daya pengguna mungkin memiliki bidangaddressId
atau tautan ke/addresses/{addressId}
). - Sumber Daya Tersemat/Sub-sumber daya: Jika suatu entitas sangat terkait dengan sumber daya induk dan tidak memiliki siklus hidup independen, mungkin lebih baik dimodelkan sebagai bagian dari representasi sumber daya induk atau sebagai sub-sumber daya yang dapat diakses melalui jalur seperti
/users/{userId}/address
. Ini dapat menyederhanakan interaksi klien jika sub-entitas selalu diakses dalam konteks induknya.
Pilihan ini sering melibatkan pertukaran:
- Chattiness: Banyak sumber daya yang sangat terperinci dapat menyebabkan lebih banyak permintaan HTTP (meningkatkan chattiness) jika klien perlu mengumpulkan gambaran lengkap dari berbagai sumber.
- Duplikasi/Kompleksitas Data: Menyematkan sumber daya dapat menyebabkan payload yang lebih besar dan potensi duplikasi data atau kompleksitas jika informasi yang disematkan juga tersedia sebagai sumber daya mandiri.
- Cacheability: Sumber daya terpisah seringkali lebih mudah di-cache secara independen.
- Atomicity Operasi: Pembaruan pada sumber daya tunggal yang kasar secara inheren bersifat atomik. Mengelola atomicity di berbagai pembaruan sumber daya yang sangat terperinci bisa lebih kompleks.
Pertimbangan yang cermat terhadap faktor-faktor ini, bersama dengan pemahaman mendalam tentang bagaimana API akan digunakan, sangat penting untuk membuat keputusan yang tepat tentang granularitas sumber daya.
Ingin platform Terintegrasi, All-in-One untuk Tim Pengembang Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
Kesimpulan
Sumber daya adalah blok bangunan fundamental dari setiap RESTful API. Mereka mewakili "benda" yang diekspos oleh API dan memungkinkan klien untuk berinteraksi dengannya. Dengan menetapkan URI unik ke sumber daya, membedakan antara sumber daya dan representasinya, dan mengatur sumber daya ke dalam koleksi logis, pengembang dapat membuat API yang intuitif, skalabel, dan mematuhi prinsip-prinsip REST.
Memahami cara mendefinisikan, mengidentifikasi, dan memanipulasi sumber daya menggunakan metode HTTP standar sangat penting bagi perancang maupun konsumen API. Ditambah dengan praktik terbaik dalam desain URI, penggunaan kode status HTTP yang tepat, dan pendekatan yang cermat terhadap granularitas sumber daya, model sumber daya yang terdefinisi dengan baik menghasilkan API yang tidak hanya fungsional tetapi juga menyenangkan untuk dikerjakan. Seiring lanskap digital terus berkembang, prinsip-prinsip arsitektur berorientasi sumber daya akan tetap menjadi landasan komunikasi layanan web yang efektif.