Cara membuat versi URI REST

111

Apa cara terbaik untuk membuat versi URI REST? Saat ini kami memiliki versi # di URI itu sendiri, yaitu.

http://example.com/users/v4/1234/

untuk versi 4 dari representasi ini.

Apakah versi tersebut termasuk dalam queryString? yaitu.

http://example.com/users/1234?version=4

Atau apakah pembuatan versi paling baik dilakukan dengan cara lain?

Mike Pone
sumber
Kemungkinan duplikat dari Praktik terbaik untuk pembuatan versi API?
Helen

Jawaban:

34

Menurut saya, menjadikannya bagian dari URI itu sendiri (opsi 1) adalah yang terbaik karena v4 mengidentifikasi sumber daya yang berbeda dari v3. Parameter kueri seperti di opsi kedua Anda paling baik digunakan untuk meneruskan info tambahan (kueri) yang terkait dengan permintaan , daripada sumber daya .

Zef Hemel
sumber
11
Pertanyaannya adalah, apakah itu SUMBER DAYA yang berbeda yang sedang kita diskusikan? Atau representasi lain dari sumber daya itu? Apakah REST membedakan antara representasi dan sumber daya?
Cheeso
1
@Cheeso - OP menunjukkan bahwa itu adalah representasi yang berbeda daripada sumber daya yang berbeda, maka jawaban saya.
Greg Beech
Ini telah dijawab secara lebih rinci sebelum di sini stackoverflow.com/q/389169/104261
Taras Alenin
+1 untuk "Parameter kueri seperti di opsi kedua Anda paling baik digunakan untuk menyampaikan info (kueri) tambahan yang terkait dengan permintaan, daripada sumber daya"
andy
Untuk representasi yang berbeda, saya pikir Anda harus menggunakan header seperti "Terima", lalu klien dapat menentukan ke server "Saya hanya menerima versi 4" dan server dapat menjawab dengan representasi itu. Jika tidak ada terima yang dikirim maka versi terakhir disediakan.
Carlos Verdes
190

Jangan membuat versi URL, karena ...

  • Anda memutus tautan permanen
  • Perubahan url akan menyebar seperti penyakit melalui antarmuka Anda. Apa yang Anda lakukan dengan representasi yang tidak berubah tetapi mengarah ke representasi yang telah berubah? Jika Anda mengubah url, Anda merusak klien lama. Jika Anda meninggalkan url, klien baru Anda mungkin tidak berfungsi.
  • Jenis media versi adalah solusi yang jauh lebih fleksibel.

Dengan asumsi bahwa sumber daya Anda mengembalikan beberapa varian application / vnd.yourcompany.user + xml, yang perlu Anda lakukan hanyalah membuat dukungan untuk jenis media application / vnd.yourcompany.userV2 + xml baru dan melalui keajaiban negosiasi konten v1 dan Klien v2 dapat hidup berdampingan dengan damai.

Dalam antarmuka RESTful, hal terdekat yang Anda miliki dengan kontrak adalah definisi jenis media yang dipertukarkan antara klien dan server.

URL yang digunakan klien untuk berinteraksi dengan server harus disediakan oleh server yang tertanam dalam representasi yang diambil sebelumnya. Satu-satunya URL yang perlu diketahui oleh klien adalah URL root antarmuka. Menambahkan nomor versi ke url hanya memiliki nilai jika Anda membuat url pada klien, yang seharusnya tidak Anda lakukan dengan antarmuka RESTful.

Jika Anda perlu membuat perubahan pada jenis media Anda yang akan merusak klien yang ada, buat yang baru dan biarkan url Anda sendiri!

Dan bagi para pembaca yang saat ini mengatakan bahwa ini tidak masuk akal jika saya menggunakan application / xml dan application / json sebagai jenis media. Bagaimana kita bisa membuat versi itu? Kamu bukan. Jenis media tersebut tidak terlalu berguna untuk antarmuka RESTful kecuali jika Anda menguraikannya menggunakan unduhan kode, di mana pembuatan versi merupakan titik diperdebatkan.

Darrel Miller
sumber
66
Untuk mengatasi poin-poin penting. 1. Anda tidak merusak tautan perma, karena tautan permanen tertaut ke versi tertentu 2. Jika semuanya berversi, ini bukan masalah. URL lama masih bisa berfungsi. Idealnya, Anda tidak ingin URL versi 4 mengembalikan kaitan ke sumber daya versi 3. 3. Mungkin
Mike Pone
10
Bayangkan jika ketika Anda meningkatkan ke versi baru dari browser web, semua favorit yang Anda bookmark rusak! Ingatlah bahwa secara konseptual pengguna menyimpan link ke sumber daya, bukan ke versi representasi sumber daya.
Darrel Miller
11
@Gili Untuk memenuhi persyaratan agar REST api menjadi deskriptif sendiri, header tipe konten harus menyediakan deskripsi semantik lengkap dari pesan tersebut. Dengan kata lain, jenis media Anda adalah kontrak data Anda. Jika Anda mengirimkan application / xml atau application / json, Anda tidak memberi tahu klien apa pun tentang apa yang terkandung dalam XML / Json itu. Saat aplikasi klien mencapai penarikan / Pelanggan / Nama Anda membuat penggandengan yang didasarkan pada informasi yang tidak ada dalam pesan. Menghilangkan kopling out-of-band sangat penting untuk mencapai RESTfulness.
Darrel Miller
6
@Gili Klien seharusnya tidak memiliki pengetahuan sebelumnya tentang URL API selain URL root. Anda tidak boleh mengikat format representasi ke URL tertentu. Dalam hal memilih jenis media, Anda benar-benar perlu memilih antara format tertentu seperti application / vnd.mycompany.myformat + xml atau yang terstandarisasi seperti, XHtml, Atom, RDF, dll.
Darrel Miller
4
Apakah masuk akal untuk menempatkan versi API sebagai kolom header yang terpisah? Seperti ini: Terima: application / com.example.myapp + json; versi = 1.0
Erik
21

Ah, aku memakai topi pemarah lamaku lagi.

Dari perspektif ReST, itu tidak masalah sama sekali. Bukan sosis.

Klien menerima URI yang ingin diikuti, dan memperlakukannya sebagai string buram. Masukkan apa pun yang Anda inginkan di dalamnya, klien tidak memiliki pengetahuan tentang pengenal versi di dalamnya.

Yang diketahui klien adalah bahwa ia dapat memproses jenis media, dan saya akan menyarankan untuk mengikuti saran Darrel. Saya pribadi juga merasa bahwa perlu mengubah format yang digunakan dalam arsitektur yang tenang sebanyak 4 kali harus membawa tanda peringatan yang sangat besar bahwa Anda melakukan kesalahan yang serius, dan sepenuhnya mengabaikan kebutuhan untuk mendesain jenis media Anda untuk ketahanan perubahan.

Namun bagaimanapun juga, klien hanya dapat memproses dokumen dengan format yang dapat dipahami, dan mengikuti tautan di dalamnya. Itu harus tahu tentang hubungan tautan (transisi). Jadi apa yang ada di URI sama sekali tidak relevan.

Saya pribadi akan memilih http: // localhost / 3f3405d5-5984-4683-bf26-aca186d21c04

Pengenal yang benar-benar valid yang akan mencegah pengembang klien atau orang lain menyentuh sistem untuk mempertanyakan apakah seseorang harus meletakkan v4 di awal atau di akhir URI (dan saya menyarankan bahwa, dari perspektif server, Anda tidak boleh memiliki 4 versi, tetapi 4 jenis media).

SerialSeb
sumber
Bagaimana jika representasi perlu berubah secara signifikan dan tidak akan kompatibel ke belakang?
Mike Pone
1
Dengan mendesain jenis media Anda dengan cara yang dapat diperluas, seperti dengan menggunakan namespace dan xsd yang dapat diperluas, atau format xml yang sudah ada seperti atom, ini seharusnya dapat dicegah. Jika Anda benar-benar harus melakukannya, jenis media lain adalah cara yang tepat.
SerialSeb
1
Saya suka jawaban yang benar-benar valid ini, tetapi saya pikir URI yang diusulkan lebih untuk menunjukkan poin daripada skenario nyata di mana Anda menginginkan URI yang 'dapat diretas'.
Dave Van den Eynde
10

Anda TIDAK boleh meletakkan versi di URL, Anda harus meletakkan versi di Terima Header permintaan - lihat posting saya di utas ini:

Praktik terbaik untuk pembuatan versi API?

Jika Anda mulai menempelkan versi di URL, Anda akan mendapatkan URL konyol seperti ini: http://company.com/api/v3.0/customer/123/v2.0/orders/4321/

Dan ada banyak masalah lain yang juga muncul - lihat blog saya: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html

jeremyh
sumber
11
Maaf, tapi saya rasa Anda tidak akan mendapatkan URL konyol seperti ini. Anda menghubungkan nomor versi ke sumber daya tertentu atau (lebih buruk) ke representasi tertentu. Itu akan konyol, IMO. Sebaliknya, Anda membuat versi API, jadi Anda tidak akan pernah memiliki lebih dari satu versi di URI.
fool4jesus
3

Ada 4 pendekatan berbeda untuk membuat versi API:

  • Menambahkan versi ke jalur URI:

    http://example.com/api/v1/foo
    
    http://example.com/api/v2/foo
    

    Jika Anda memiliki perubahan yang mengganggu, Anda harus menaikkan versi seperti: v1, v2, v3 ...

    Anda dapat menerapkan pengontrol dalam kode Anda seperti ini:

    @RestController
    public class FooVersioningController {
    
    @GetMapping("v1/foo")
    public FooV1 fooV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping("v2/foo")
    public FooV2 fooV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • Minta versi parameter:

    http://example.com/api/v2/foo/param?version=1
    http://example.com/api/v2/foo/param?version=2
    

    Parameter versi dapat bersifat opsional atau wajib tergantung pada bagaimana Anda ingin API digunakan.

    Implementasinya bisa serupa dengan ini:

    @GetMapping(value = "/foo/param", params = "version=1")
    public FooV1 paramV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/param", params = "version=2")
    public FooV2 paramV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • Meneruskan tajuk khusus:

    http://localhost:8080/foo/produces
    

    Dengan tajuk:

    headers[Accept=application/vnd.company.app-v1+json]
    

    atau:

    headers[Accept=application/vnd.company.app-v2+json]
    

    Keuntungan terbesar dari skema ini sebagian besar adalah semantik: Anda tidak mengacaukan URI dengan apa pun yang berkaitan dengan pembuatan versi.

    Penerapan yang mungkin:

    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v1+json")
    public FooV1 producesV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v2+json")
    public FooV2 producesV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • Mengubah Nama Host atau menggunakan API Gateways:

    Pada dasarnya, Anda memindahkan API dari satu nama host ke yang lain. Anda bahkan dapat menyebut gedung ini sebagai API baru untuk sumber daya yang sama.

    Selain itu, Anda dapat melakukan ini menggunakan API Gateways.

Javier C.
sumber
2

Jika layanan REST memerlukan autentikasi sebelum digunakan, Anda dapat dengan mudah mengaitkan kunci / token API dengan versi API dan melakukan perutean secara internal. Untuk menggunakan versi baru API, kunci API baru mungkin diperlukan, ditautkan ke versi itu.

Sayangnya, solusi ini hanya berfungsi untuk API berbasis auth. Namun, itu membuat versi di luar URI.

UberSteve
sumber
2

Saya ingin membuat API berversi dan menurut saya artikel ini sangat berguna:

http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http

Ada bagian kecil di "Saya ingin API saya diversi". Saya menganggapnya sederhana dan mudah dimengerti. Intinya adalah menggunakan bidang Terima di tajuk untuk menyampaikan informasi versi.

Asma Zubair
sumber
1

Saya akan menyertakan versi sebagai nilai opsional di akhir URI. Ini bisa berupa sufiks seperti / V4 atau parameter kueri seperti yang Anda jelaskan. Anda bahkan dapat mengalihkan / V4 ke parameter kueri sehingga Anda mendukung kedua variasi.

Paul Morgan
sumber
1

Jika Anda menggunakan URI untuk pembuatan versi, maka nomor versinya harus ada di URI root API, sehingga setiap pengenal sumber daya dapat menyertakannya.

Secara teknis, REST API tidak rusak oleh perubahan URL (hasil dari batasan antarmuka seragam). Itu hanya rusak ketika semantik terkait (misalnya kosa kata RDF khusus API) berubah dengan cara yang tidak kompatibel ke belakang (jarang). Saat ini banyak ppl tidak menggunakan tautan untuk navigasi (batasan HATEOAS) dan kosakata untuk memberi anotasi pada respons REST mereka (batasan pesan deskriptif sendiri), itulah sebabnya klien mereka putus.

Jenis MIME khusus dan pembuatan versi jenis MIME tidak membantu, karena meletakkan metadata terkait dan struktur representasi ke dalam string pendek tidak akan berfungsi. Ofc. metadata dan strukturnya akan sering berubah, begitu juga nomor versinya ...

Jadi, untuk menjawab pertanyaan Anda, cara terbaik untuk membuat anotasi permintaan dan tanggapan Anda dengan vocab ( Hydra , data tertaut ) dan lupakan versi atau gunakan hanya dengan perubahan vocab yang tidak kompatibel ke belakang (misalnya jika Anda ingin mengganti kosakata dengan yang lain).

inf3rno
sumber
0

Saya memilih untuk melakukan ini dalam jenis pantomim tetapi tidak di URL. Tapi alasannya tidak sama dengan cowok lain.

Saya pikir URL harus unik (kecuali pengalihan tersebut) untuk menemukan sumber daya yang unik. Jadi, jika Anda menerima /v2.0dalam URL, mengapa tidak /ver2.0atau /v2/atau /v2.0.0? Atau bahkan -alphadan -beta? (maka itu benar-benar menjadi konsep semver )

Jadi, versi dalam tipe mime lebih dapat diterima daripada URL.

Yarco
sumber