TL;DR
Pembuatan versi URL (/v1/pets) adalah strategi pembuatan versi API yang paling praktis untuk sebagian besar tim. Ini terlihat, dapat di-cache, dan mudah diuji. Pembuatan versi header dan negosiasi konten lebih "murni" REST tetapi menambah kerumitan. Modern PetstoreAPI menggunakan pembuatan versi URL dengan pembuatan versi semantik dan kebijakan penghentian yang jelas.
Pendahuluan
API Anda membutuhkan perubahan yang merusak. Anda mengubah format respons untuk /pets dari array kosong menjadi objek terbungkus dengan metadata paginasi. Klien yang ada akan rusak. Apa yang Anda lakukan?
Anda memerlukan pembuatan versi API. Tapi strategi mana? Pembuatan versi URL (/v1/pets vs /v2/pets)? Pembuatan versi header (Accept: application/vnd.petstore.v1+json)? Negosiasi konten? Setiap pendekatan memiliki pendukung yang antusias dan opini yang kuat.
Jawabannya: pembuatan versi URL menang untuk sebagian besar tim. Ini pragmatis, terlihat, dan berfungsi dengan semua peralatan HTTP. Pembuatan versi header dan negosiasi konten secara teoritis lebih bersih tetapi menambah kerumitan yang tidak dibutuhkan sebagian besar tim.
Modern PetstoreAPI menggunakan pembuatan versi URL dengan pembuatan versi semantik dan kebijakan penghentian yang jelas. Versi saat ini adalah v1, dengan v2 direncanakan untuk perubahan yang merusak di masa mendatang.
Dalam panduan ini, Anda akan mempelajari tiga strategi pembuatan versi utama, pro dan kontranya, serta cara menerapkan pembuatan versi dengan benar menggunakan Modern PetstoreAPI sebagai referensi.
Mengapa API Membutuhkan Pembuatan Versi
API berkembang. Anda menambahkan fitur, memperbaiki bug, dan meningkatkan desain. Terkadang perubahan ini merusak klien yang sudah ada.
Perubahan yang Merusak
Perubahan yang merusak klien yang sudah ada:
1. Menghapus field:
// v1
{"id": "123", "name": "Fluffy", "age": 3}
// v2 (merusak: age dihapus)
{"id": "123", "name": "Fluffy"}
2. Mengubah tipe field:
// v1
{"price": "19.99"}
// v2 (merusak: string menjadi number)
{"price": 19.99}
3. Mengubah struktur respons:
// v1 (array kosong)
[{"id": "123"}]
// v2 (merusak: objek terbungkus)
{"data": [{"id": "123"}], "pagination": {...}}
4. Mengubah struktur URL:
// v1
GET /pet/123
// v2 (merusak: jamak)
GET /pets/123
5. Mengubah otentikasi:
// v1: API key di kueri
GET /pets?api_key=xxx
// v2 (merusak: token Bearer)
GET /pets
Authorization: Bearer xxx
Perubahan yang Tidak Merusak
Perubahan yang tidak merusak klien:
- Menambahkan endpoint baru
- Menambahkan field opsional ke permintaan
- Menambahkan field baru ke respons (klien harus mengabaikan field yang tidak dikenal)
- Menambahkan parameter kueri baru
- Menambahkan metode HTTP baru ke sumber daya yang ada
Keputusan Pembuatan Versi
Saat Anda membutuhkan perubahan yang merusak, Anda memiliki dua pilihan:
1. Memaksa semua klien untuk meng-upgrade - Sederhana tetapi merusak integrasi yang ada
2. Mendukung beberapa versi - Lebih banyak pekerjaan tetapi mempertahankan kompatibilitas mundur
Sebagian besar API publik memilih opsi 2. Pembuatan versi memungkinkan Anda mengembangkan API sambil memberi waktu kepada klien untuk bermigrasi.
Pembuatan Versi URL
Pembuatan versi URL menempatkan nomor versi di jalur URL.
Cara Kerjanya
GET /v1/pets
GET /v2/pets
Versi adalah bagian dari pengidentifikasi sumber daya. Versi yang berbeda adalah sumber daya yang berbeda.
Kelebihan
1. Terlihat dan eksplisit
Versi ada di URL. Anda dapat melihatnya di log, riwayat peramban, dan dokumentasi. Tidak ada header tersembunyi yang perlu diingat.
2. Mudah diuji
curl https://petstoreapi.com/v1/pets
curl https://petstoreapi.com/v2/pets
Anda dapat menguji kedua versi dengan permintaan HTTP sederhana.
3. Berfungsi dengan semua peralatan HTTP
Peramban, cache, proksi, dan penyeimbang beban melihat URL yang berbeda. Mereka dapat merutekan, menyimpan, dan mencatat setiap versi secara independen.
4. Sederhana untuk klien
Klien hanya perlu mengubah URL. Tidak ada header kustom atau logika negosiasi konten.
5. Mudah untuk dihentikan
Anda dapat menghapus endpoint /v1 tanpa memengaruhi /v2.
Kekurangan
1. Bukan REST "murni"
Penganut REST yang murni berpendapat bahwa /v1/pets/123 dan /v2/pets/123 adalah sumber daya yang sama, jadi mereka harus memiliki URL yang sama. Versi harus berada di header atau negosiasi konten.
2. Polusi URL
API Anda memiliki beberapa ruang URL: /v1/*, /v2/*, dll.
3. Lebih sulit untuk membuat versi sumber daya individual
Jika Anda ingin membuat versi hanya satu endpoint, Anda perlu membuat versi seluruh API atau menciptakan inkonsistensi.
Implementasi
Versi utama di URL:
/v1/pets
/v2/pets
Jangan sertakan versi minor:
❌ /v1.2/pets (terlalu granular)
✅ /v1/pets (hanya versi utama)
Gunakan pembuatan versi semantik secara internal:
- v1.0.0 - Rilis awal
- v1.1.0 - Menambahkan field baru (tidak merusak)
- v1.2.0 - Menambahkan endpoint baru (tidak merusak)
- v2.0.0 - Perubahan yang merusak (URL baru: /v2)
Modern PetstoreAPI menggunakan pembuatan versi URL dengan /v1 sebagai versi saat ini.
Pembuatan Versi Header
Pembuatan versi header menempatkan versi di header HTTP kustom.
Cara Kerjanya
GET /pets
API-Version: 1
GET /pets
API-Version: 2
URL tetap sama. Header menentukan versi.
Kelebihan
1. URL yang bersih
/pets sama untuk semua versi. Tanpa awalan /v1 atau /v2.
2. Lebih "RESTful"
Pengidentifikasi sumber daya (/pets/123) tidak berubah. Representasi berubah berdasarkan header.
3. Pembuatan versi yang terperinci
Anda dapat membuat versi sumber daya individual:
GET /pets
API-Version: 2
GET /orders
API-Version: 1
Kekurangan
1. Tidak terlihat
Versi tidak ada di URL. Anda tidak dapat melihatnya di log atau riwayat peramban tanpa memeriksa header.
2. Lebih sulit diuji
curl -H "API-Version: 1" https://petstoreapi.com/pets
curl -H "API-Version: 2" https://petstoreapi.com/pets
Anda harus ingat untuk menyertakan header.
3. Kompleksitas caching
Cache harus mempertimbangkan header API-Version. Anda memerlukan Vary: API-Version di respons.
4. Kompleksitas klien
Klien memerlukan logika header kustom. Tidak semua klien HTTP membuatnya mudah.
5. Ambiguitas versi default
Apa yang terjadi jika klien tidak mengirimkan header? Anda memerlukan default, yang menciptakan perilaku implisit.
Implementasi
Header kustom:
API-Version: 1
Atau gunakan header Accept:
Accept: application/vnd.petstore.v1+json
Sertakan header Vary:
Vary: API-Version
Ini memberitahu cache untuk mempertimbangkan header saat melakukan caching.
Negosiasi Konten
Negosiasi konten menggunakan header Accept dengan tipe media kustom.
Cara Kerjanya
GET /pets
Accept: application/vnd.petstore.v1+json
GET /pets
Accept: application/vnd.petstore.v2+json
Versi adalah bagian dari tipe media.
Kelebihan
1. Paling "RESTful"
Beginilah cara REST dirancang. Representasi yang berbeda dari sumber daya yang sama.
2. Mengikuti standar HTTP
Menggunakan negosiasi konten HTTP standar.
3. Mendukung banyak format
Anda dapat membuat versi dan memformat secara bersamaan:
Accept: application/vnd.petstore.v1+json
Accept: application/vnd.petstore.v1+xml
Kekurangan
1. Kompleks
Klien harus memahami tipe media dan negosiasi konten.
2. Lebih sulit diuji
curl -H "Accept: application/vnd.petstore.v1+json" https://petstoreapi.com/pets
3. Dukungan peralatan yang buruk
Banyak klien dan peralatan HTTP tidak menangani tipe media kustom dengan baik.
4. Kompleksitas caching
Cache harus mempertimbangkan header Accept. Anda memerlukan Vary: Accept.
5. Berlebihan untuk sebagian besar API
Sebagian besar API tidak memerlukan tingkat kecanggihan ini.
Implementasi
Tipe media spesifik vendor:
Accept: application/vnd.petstore.v1+json
Respons:
Content-Type: application/vnd.petstore.v1+json
Vary: Accept
Bagaimana Modern PetstoreAPI Menerapkan Pembuatan Versi
Modern PetstoreAPI menggunakan pembuatan versi URL dengan kebijakan yang jelas.
Versi Saat Ini: v1
https://petstoreapi.com/v1/pets
https://petstoreapi.com/v1/orders
https://petstoreapi.com/v1/users
Semua endpoint berada di bawah /v1.
Header Respons Versi
Setiap respons menyertakan versi API:
X-API-Version: 1.2.0
Ini menunjukkan versi persisnya (major.minor.patch) meskipun URL hanya menunjukkan versi utama.
Peringatan Penghentian
Ketika suatu versi dihentikan, respons menyertakan:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"
Deprecation- Menunjukkan versi dihentikanSunset- Kapan versi akan dihapusLink- Panduan migrasi
Penemuan Versi
Endpoint root mencantumkan versi yang tersedia:
GET https://petstoreapi.com/
{
"versions": [
{
"version": "v1",
"status": "current",
"docsUrl": "https://docs.petstoreapi.com/v1"
}
]
}
Pembuatan Versi Semantik
Modern PetstoreAPI mengikuti pembuatan versi semantik secara internal:
- Mayor (v1, v2) - Perubahan yang merusak, URL baru
- Minor (v1.1, v1.2) - Fitur baru, kompatibel mundur
- Patch (v1.1.1, v1.1.2) - Perbaikan bug, kompatibel mundur
Hanya versi mayor yang muncul di URL.
Menguji Versi API dengan Apidog
Apidog membantu Anda menguji berbagai versi API.
Mengimpor Berbagai Versi
Impor spesifikasi OpenAPI untuk setiap versi:
petstore-v1.yaml → Lingkungan: v1
petstore-v2.yaml → Lingkungan: v2
Menjalankan Pengujian Terhadap Semua Versi
Buat rangkaian pengujian yang berjalan terhadap kedua versi:
// Uji v1
pm.environment.set("baseUrl", "https://petstoreapi.com/v1");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");
// Uji v2
pm.environment.set("baseUrl", "https://petstoreapi.com/v2");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");
Memvalidasi Perilaku Spesifik Versi
Uji bahwa v1 dan v2 berperilaku berbeda:
// v1 mengembalikan array kosong
pm.test("v1 mengembalikan array", function() {
pm.expect(pm.response.json()).to.be.an('array');
});
// v2 mengembalikan objek terbungkus
pm.test("v2 mengembalikan objek terbungkus", function() {
pm.expect(pm.response.json()).to.have.property('data');
pm.expect(pm.response.json()).to.have.property('pagination');
});
Memeriksa Header Penghentian
Uji bahwa versi yang dihentikan menyertakan header yang tepat:
pm.test("Versi yang dihentikan menyertakan header", function() {
pm.response.to.have.header("Deprecation");
pm.response.to.have.header("Sunset");
});
Strategi Penghentian Versi
Cara menghentikan versi lama tanpa merusak klien.
1. Umumkan Penghentian Lebih Awal
Beri klien setidaknya pemberitahuan 6-12 bulan:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
2. Sediakan Panduan Migrasi
Dokumentasikan semua perubahan yang merusak dan cara bermigrasi:
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"
3. Pantau Penggunaan
Lacak klien mana yang masih menggunakan versi yang dihentikan:
X-API-Version: 1.2.0
X-Client-ID: abc123
Hubungi klien secara langsung jika diperlukan.
4. Penonaktifan Bertahap
Jangan segera menghapus versi:
- Bulan 1-6: Umumkan penghentian
- Bulan 7-9: Tambahkan header penghentian
- Bulan 10-11: Kurangi batas kecepatan untuk versi yang dihentikan
- Bulan 12: Hapus versi yang dihentikan
5. Pertahankan Dokumentasi
Bahkan setelah dihapus, simpan dokumentasi untuk versi lama. Klien mungkin perlu merujuknya.
Kesimpulan
Pembuatan versi URL adalah strategi pembuatan versi API yang paling praktis untuk sebagian besar tim. Ini terlihat, mudah diuji, dan berfungsi dengan semua peralatan HTTP. Pembuatan versi header dan negosiasi konten lebih "murni" REST tetapi menambah kerumitan.
Modern PetstoreAPI menggunakan pembuatan versi URL dengan /v1 sebagai versi saat ini, pembuatan versi semantik secara internal, dan kebijakan penghentian yang jelas. Pendekatan ini menyeimbangkan pragmatisme dengan desain API yang baik.
Gunakan Apidog untuk menguji berbagai versi API, memvalidasi perilaku spesifik versi, dan memastikan migrasi yang lancar antar versi.
FAQ
Haruskah saya menggunakan pembuatan versi URL atau pembuatan versi header?
Gunakan pembuatan versi URL kecuali Anda memiliki alasan khusus untuk tidak melakukannya. Ini lebih sederhana, lebih terlihat, dan lebih mudah diuji. Pembuatan versi header lebih "RESTful" tetapi menambah kerumitan yang tidak dibutuhkan sebagian besar tim.
Berapa banyak versi yang harus saya dukung secara bersamaan?
Dukung maksimal 2 versi: saat ini dan sebelumnya. Mendukung lebih banyak menciptakan beban pemeliharaan. Beri klien 6-12 bulan untuk bermigrasi, lalu hapus versi lama.
Haruskah saya membuat versi dari v0 atau v1?
Mulai dengan v1. v0 menyiratkan ketidakstabilan. Jika API Anda belum cukup stabil untuk v1, jangan rilis secara publik dulu.
Apakah saya perlu membuat versi setiap endpoint?
Tidak. Hanya buat versi ketika Anda membuat perubahan yang merusak. Jika Anda menambahkan endpoint baru tanpa mengubah yang sudah ada, Anda tidak memerlukan versi baru.
Bagaimana dengan versi minor di URL?
Jangan sertakan versi minor di URL. Gunakan /v1, bukan /v1.2. Versi minor kompatibel mundur, sehingga klien tidak perlu mengubah URL.
Bagaimana saya menangani bug spesifik versi?
Perbaiki bug di semua versi yang didukung. Jika bug hanya ada di v1, perbaiki di v1. Jangan memaksa klien untuk meng-upgrade ke v2 untuk perbaikan bug.
Haruskah saya menggunakan pembuatan versi semantik?
Ya, secara internal. Lacak versi major.minor.patch, tetapi hanya ekspos versi mayor di URL. Ini memberi Anda fleksibilitas untuk perubahan yang tidak merusak.
Bagaimana jika saya hanya perlu membuat versi satu endpoint?
Dengan pembuatan versi URL, Anda perlu membuat versi seluruh API atau menciptakan inkonsistensi. Ini adalah kompromi. Sebagian besar tim menerima pembuatan versi seluruh API demi kesederhanaan.
