Versi API REST

1. Masalahnya

Mengembangkan API REST adalah masalah yang sukar - satu di mana terdapat banyak pilihan. Artikel ini membincangkan beberapa pilihan ini.

2. Apa yang ada dalam Kontrak?

Sebelum ada perkara lain, kita perlu menjawab satu soalan mudah: Apakah Kontrak antara API dan Pelanggan?

2.1. URI adalah sebahagian daripada Kontrak?

Mari kita pertimbangkan struktur URI API REST - adakah bahagian kontrak itu? Sekiranya pelanggan menanda buku, kod keras dan umumnya bergantung pada URI API?

Sekiranya ini berlaku, maka interaksi Pelanggan dengan Perkhidmatan REST tidak lagi didorong oleh Perkhidmatan itu sendiri, tetapi oleh apa yang Roy Fielding memanggil maklumat di luar jalur :

API REST harus dimasukkan tanpa pengetahuan sebelumnya di luar URI awal (penanda buku) dan sekumpulan jenis media standard yang sesuai untuk khalayak yang dimaksudkan ... Kegagalan di sini menunjukkan bahawa maklumat di luar jalur mendorong interaksi dan bukannya hiperteks.

Oleh itu, jelas URI bukan sebahagian daripada kontrak ! Pelanggan hanya perlu mengetahui satu URI - titik masuk ke API. Semua URI lain mesti dijumpai semasa menggunakan API.

2.2. Jenis Media bahagian dalam Kontrak?

Bagaimana dengan maklumat Jenis Media yang digunakan untuk perwakilan Sumber - adakah ini adalah bahagian kontrak antara Pelanggan dan Perkhidmatan?

Untuk berjaya menggunakan API, Pelanggan mesti mempunyai pengetahuan terlebih dahulu mengenai Jenis Media ini . Sebenarnya, definisi jenis media ini mewakili keseluruhan kontrak.

Oleh itu, di sinilah Perkhidmatan REST harus memberi tumpuan paling banyak:

API REST harus menghabiskan hampir semua usaha deskriptifnya dalam menentukan jenis media yang digunakan untuk mewakili sumber dan mendorong keadaan aplikasi, atau dalam menentukan nama hubungan yang diperpanjang dan / atau mark-up yang diaktifkan hiperteks untuk jenis media standard yang ada.

Oleh itu, definisi Jenis Media adalah sebahagian daripada kontrak dan harus menjadi pengetahuan terdahulu bagi pelanggan yang menggunakan API. Di sinilah standardisasi masuk.

Kami sekarang mempunyai idea yang baik tentang apa kontraknya, mari kita beralih ke bagaimana sebenarnya mengatasi masalah versi.

3. Pilihan Tahap Tinggi

Sekarang mari kita bincangkan pendekatan tahap tinggi untuk membuat versi REST API:

  • URI Versioning - versi ruang URI menggunakan petunjuk versi
  • Versi Media Versi - versi Perwakilan Sumber

Apabila kami memperkenalkan versi di ruang URI, Representasi Sumber dianggap tidak berubah. Oleh itu, apabila perubahan perlu diperkenalkan di API, ruang URI baru perlu dibuat.

Sebagai contoh, katakanlah API menerbitkan sumber berikut - pengguna dan hak istimewa:

//host/v1/users //host/v1/privileges

Sekarang, mari kita pertimbangkan bahawa perubahan mendadak dalam API pengguna memerlukan memperkenalkan versi kedua:

//host/v2/users //host/v2/privileges

Apabila kami menerbitkan Jenis Media dan memperluas bahasa, kami menjalani Rundingan Kandungan berdasarkan tajuk ini. REST API akan menggunakan jenis media MIME vendor tersuai dan bukannya jenis media generik seperti aplikasi / json . Kami akan menerbitkan jenis media ini dan bukannya URI.

Sebagai contoh:

===> GET /users/3 HTTP/1.1 Accept: application/vnd.myname.v1+json <=== HTTP/1.1 200 OK Content-Type: application/vnd.myname.v1+json { "user": { "name": "John Smith" } }

Kami dapat melihat artikel 'Jenis Media Khusus untuk API Rehat' ini untuk mendapatkan maklumat dan contoh lebih lanjut mengenai perkara ini.

Apa yang penting untuk difahami di sini ialah pelanggan tidak membuat andaian mengenai struktur tindak balas melebihi apa yang ditentukan dalam jenis media.

Inilah sebabnya mengapa jenis media generik tidak sesuai. Ini tidak memberikan maklumat semantik yang cukup dan memaksa pelanggan untuk menggunakan memerlukan petunjuk tambahan untuk memproses representasi sumber yang sebenarnya.

Pengecualian untuk ini adalah menggunakan cara lain untuk mengenal pasti semantik kandungan secara unik - seperti skema XML.

4. Kelebihan dan Kekurangan

Sekarang kita mempunyai konsep yang jelas tentang apa yang menjadi sebahagian daripada Kontrak antara Pelanggan dan Perkhidmatan, serta gambaran umum mengenai pilihan untuk versi API, mari kita bincangkan kelebihan dan kekurangan setiap pendekatan.

Pertama, memperkenalkan pengecam versi dalam URI membawa jejak URI yang sangat besar. Ini disebabkan oleh fakta bahawa perubahan yang mematikan dalam mana-mana API yang diterbitkan akan memperkenalkan pohon representasi baru untuk keseluruhan API. Lama kelamaan, ini menjadi beban untuk dipertahankan dan juga masalah bagi pelanggan - yang kini mempunyai lebih banyak pilihan untuk dipilih.

Pengecam versi dalam URI juga sangat tidak fleksibel . Tidak ada cara untuk hanya mengembangkan API dari satu Sumber, atau sebahagian kecil dari keseluruhan API.

Seperti yang kami sebutkan sebelumnya, ini adalah pendekatan semua atau tidak. Sekiranya sebahagian dari API berpindah ke versi baru, maka keseluruhan API harus bergerak bersama dengannya. Ini juga menjadikan peningkatan pelanggan dari v1 ke v2 sebagai usaha utama - yang membawa kepada peningkatan yang lebih perlahan dan tempoh terbenam yang lebih lama untuk versi lama.

HTTP Caching juga menjadi perhatian utama dalam hal versi.

Dari perspektif proxy cache di tengah, setiap pendekatan mempunyai kelebihan dan kekurangan. Sekiranya URI diubahsuai, maka cache perlu menyimpan banyak salinan setiap Sumber - satu untuk setiap versi API. Ini meletakkan beban pada cache dan mengurangkan kadar hit cache kerana klien yang berbeza akan menggunakan versi yang berbeza.

Also, some cache invalidation mechanisms will no longer work. If the media type is the one that is versioned, then both the Client and the Service need to support the Vary HTTP header to indicate that there are multiple versions being cached.

From the perspective of client caching however, the solution that versions the media type involves slightly more work than the one where URIs contain the version identifier. This is because it's simply easier to cache something when its key is an URL than a media type.

Let's end this section with defining some goals (straight out of API Evolution):

  • keep compatible changes out of names
  • avoid new major versions
  • makes changes backwards-compatible
  • think about forwards-compatibility

5. Possible Changes to the API

Next, let's consider the types of changes to the REST API – these are introduced here:

  • representation format changes
  • resource changes

5.1. Adding to the Representation of a Resource

The format documentation of the media type should be designed with forward compatibility in mind. Specifically, a client should ignore information that it doesn't understand (which JSON does better than XML).

Now, adding information in the Representation of a resource will not break existing clients if these are correctly implemented.

To continue our earlier example, adding the amount in the representation of the user will not be a breaking change:

{ "user": { "name": "John Smith", "amount": "300" } }

5.2. Removing or Changing an Existing Representation

Removing, renaming or generally restructuring information in the design of existing representations is a breaking change for clients. This is because they already understand and rely on the old format.

This is where Content Negotiation comes in. For such changes, we can add a new vendor MIME media type.

Let's continue with the previous example. Say we want to break the name of the user into firstname and lastname:

===> GET /users/3 HTTP/1.1 Accept: application/vnd.myname.v2+json <=== HTTP/1.1 200 OK Content-Type: application/vnd.myname.v2+json { "user": { "firstname": "John", "lastname": "Smith", "amount": "300" } }

As such, this does represent an incompatible change for the Client – which will have to request the new Representation and understand the new semantics. However, the URI space will remain stable and will not be affected.

5.3. Major Semantic Changes

These are changes in the meaning of the Resources, the relations between them or what the map to in the backend. This kind of changes may require a new media type, or they may require publishing a new, sibling Resource next to the old one and making use of linking to point to it.

While this sounds like using version identifiers in the URI all over again, the important distinction is that the new Resource is published independently of any other Resources in the API and will not fork the entire API at the root.

The REST API should adhere to the HATEOAS constraint. According to this, most of the URIs should be DISCOVERED by Clients, not hardcoded. Changing such an URI should not be considered an incompatible change. The new URI can replace the old one and Clients will be able to re-discover the URI and still function.

It's worth noting however that, while using version identifiers in the URI is problematic for all of these reasons, it is not un-RESTful in any way.

6. Conclusion

This article tried to provide an overview of the very diverse and difficult problem of evolving a REST Service. We discussed the two common solutions, advantages and disadvantages of each one, and ways to reason about these approaches in the context of REST.

Artikel ini diakhiri dengan membuat pilihan untuk penyelesaian kedua - memformat jenis media sambil memeriksa kemungkinan perubahan pada RESTful API.

Pelaksanaan penuh tutorial ini boleh didapati dalam projek GitHub.

7. Bacaan Lebih Lanjut

Biasanya, sumber bacaan ini dihubungkan di seluruh artikel, tetapi dalam kes ini, terdapat terlalu banyak sumber yang baik:

    • API REST mesti didorong oleh hiperteks
    • Evolusi API
    • Memaut untuk API HTTP
    • Strategi Keserasian