Versionnage d’une API REST

Versionnage d'une API REST

1. Le problème

Evolving a REST API est un problème difficile - un pour lequel de nombreuses options sont disponibles. Cet article décrit certaines de ces options.

Lectures complémentaires:

Spring Boot Tutorial - Démarrer une application simple

Voici comment vous commencez à comprendre Spring Boot.

Read more

Explorer le Spring TestRestTemplate

Apprenez à utiliser le nouveau TestRestTemplate dans Spring Boot pour tester une API simple.

Read more

API REST avec Jersey et Spring

Création de services Web reposants à l’aide de Jersey 2 et Spring.

Read more

2. Qu'y a-t-il dans le contrat?

Avant toute chose, nous devons répondre à une question simple:What is the Contract between the API and the Client?

2.1. Les URI font-ils partie du contrat?

Considérons d'abordthe URI structure of the REST API - cela fait-il partie du contrat? Les clients doivent-ils mettre en signet, coder en dur et généralement compter sur les URI de l'API?

Si tel est le cas, alors l'interaction du Client avec le Service REST ne serait plus pilotée par le Service lui-même, mais par les informations deRoy Fielding callsout-of-band:

Une API REST doit être entrée sans aucune connaissance préalable au-delà de l'URI initial (signet) et d'un ensemble de types de média normalisés adaptés au public cible… Une défaillance ici implique que des informations hors bande génèrent une interaction plutôt qu'un hypertexte.

Donc clairementURIs are not part of the contract! Le client ne doit connaître qu'un seul URI, le point d'entrée de l'API. Tous les autres URI doivent être découverts lors de l'utilisation de l'API.

2.2. Les types de médias font-ils partie du contrat?

Qu'en est-il des informations sur le type de support utilisées pour la représentation des ressources - ces informations font-elles partie du contrat entre le client et le service?

In order to successfully consume the API, the Client must have prior knowledge of these Media Types. En fait, la définition de ces types de médias représente l’ensemble du contrat.

C'est pourquoi le service REST devrait se concentrer davantage:

Une API REST doit consacrer la quasi-totalité de ses efforts descriptifs à la définition du ou des types de support utilisés pour représenter les ressources et piloter l'état de l'application, ou à la définition de noms de relations étendues et / ou de balises hypertextes pour les types de supports standard existants.

Donc, lesMedia Type definitions are part of the contract et devraient être des connaissances préalables pour le client qui consomme l'API. C'est ici qu'intervient la normalisation.

Nous avons maintenant une bonne idée de ce qu'est le contrat, passons à la manière de résoudre réellement le problème de version.

3. Options de haut niveau

Voyons maintenant les approches de haut niveau de la gestion des versions de l'API REST:

  • URI Versioning - version de l'espace URI à l'aide des indicateurs de version

  • Media Type Versioning - version la représentation de la ressource

When we introduce the version in the URI space, the Representations of Resources are considered immutable. Ainsi, lorsque des modifications doivent être introduites dans l'API, un nouvel espace URI doit être créé.

Par exemple, supposons qu'une API publie les ressources suivantes - utilisateurs et privilèges:

http://host/v1/users
http://host/v1/privileges

Maintenant, considérons qu'un changement radical dans l'APIusers nécessite l'introduction d'une deuxième version:

http://host/v2/users
http://host/v2/privileges

When we version the Media Type and extend the language, we go through Content Negotiation based on this header. L'API REST utiliserait desvendor MIME media types personnalisés au lieu de types de supports génériques tels queapplication/json. Nous allons versionner ces types de médias au lieu des URI.

Par exemple:

===>
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"
    }
}

Nous pouvons consulter ce‘Custom Media Types for Rest APIs' article pour plus d'informations et des exemples à ce sujet.

Il est important de comprendre ici quethe client makes no assumptions about the structure of the response au-delà de ce qui est défini dans le type de média.

C'est pourquoi les types de média génériques ne sont pas idéaux. Cesdo not provide enough semantic information et forcent le client à utiliser nécessitent des conseils supplémentaires pour traiter la représentation réelle de la ressource.

Une exception à cette règle consiste à utiliser une autre méthode d'identification unique de la sémantique du contenu, telle qu'un schéma XML.

4. Avantages et inconvénients

Maintenant que nous avons un concept clair de ce qui fait partie du contrat entre le client et le service, ainsi qu'un aperçu de haut niveau des options de version de l'API, discutons des avantages et des inconvénients de chaque approche.

Premièrement,introducing version identifiers in the URI leads to a very large URI footprint. Cela est dû au fait que tout changement de rupture dans l'une des API publiées introduira une toute nouvelle arborescence de représentations pour l'ensemble de l'API. Avec le temps, cela devient un fardeau à gérer ainsi qu'un problème pour le client - qui dispose désormais de plus d'options parmi lesquelles choisir.

Version identifiers in the URI ARE also severely inflexible. Il est impossible de faire évoluer simplement l'API d'une seule ressource ou d'un petit sous-ensemble de l'API global.

Comme nous l'avons mentionné précédemment, il s'agit d'une approche tout ou rien. Si une partie de l'API passe à la nouvelle version, alors toute l'API doit être déplacée. Cela fait également de la mise à niveau des clients de v1 à v2 une entreprise majeure - ce qui entraîne des mises à niveau plus lentes et des périodes de désactivation beaucoup plus longues pour les anciennes versions.

La mise en cache HTTP est également une préoccupation majeure en matière de gestion des versions.

Du point de vue des caches proxy au milieu, chaque approche présente des avantages et des inconvénients. Si l'URI est versionné, le cache devra conserver plusieurs copies de chaque ressource, une pour chaque version de l'API. Cela met le cache en charge et réduit le taux de réussite du cache, car différents clients utiliseront des versions différentes.

De plus, certains mécanismes d'invalidation de cache ne fonctionneront plus. Si le type de support est celui qui est versionné, le client et le service doivent prendre en charge lesVary HTTP header pour indiquer qu'il existe plusieurs versions mises en cache.

Cependant, à partir desperspective of client caching, la solution qui verse le type de média implique un peu plus de travail que celle où les URI contiennent l'identificateur de version. En effet, il est tout simplement plus facile de mettre en cache quelque chose lorsque sa clé est une URL qu’un type de média.

Terminons cette section en définissant quelques objectifs (tout droit sortis deAPI Evolution):

  • garder les modifications compatibles en dehors des noms

  • éviter les nouvelles versions majeures

  • rend les modifications compatibles avec les versions antérieures

  • penser à la compatibilité en aval

5. Modifications possibles de l'API

Examinons ensuite les types de modifications apportées à l'API REST - elles sont présentées ici:

  • changements de format de représentation

  • changements de ressources

5.1. Ajout à la représentation d'une ressource

La documentation de format du type de support doit être conçue avec une compatibilité ascendante en tête. Plus précisément, un client doit ignorer les informations qu'il ne comprend pas (ce que JSON fait mieux que XML).

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

Pour continuer notre exemple précédent, ajouter lesamount dans la représentation desuser ne sera pas un changement radical:

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

5.2. Suppression ou modification d'une représentation existante

Removing, renaming or generally restructuring information in the design of existing representations is a breaking change for clients. Ceci est dû au fait qu'ils comprennent déjà et s'appuient déjà sur l'ancien format.

C’est là que la négociation de contenu entre en jeu. Pour de tels changements,we can add a new vendor MIME media type.

Continuons avec l'exemple précédent. Disons que nous voulons diviser lesname desuser enfirstname etlastname:

===>
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"
    }
}

En tant que tel, cela représente un changement incompatible pour le client - qui devra demander la nouvelle représentation et comprendre la nouvelle sémantique. Cependant, l'espace URI restera stable et ne sera pas affecté.

5.3. Changements sémantiques majeurs

These are changes in the meaning of the Resources, the relations between them or what the map to in the backend. Ce type de changements peut nécessiter un nouveau type de média, ou ils peuvent exiger la publication d'une nouvelle Ressource sœur à côté de l'ancienne et en utilisant des liens pour pointer vers elle.

Bien que cela ressemble à utiliser à nouveau les identificateurs de version dans l'URI, la distinction importante est que la nouvelle ressourceis published independently of any other Resources in the API et ne fera pas bifurquer l'API entière à la racine.

The REST API should adhere to the HATEOAS constraint. Selon cela, la plupart des URI doivent être DÉCOUVERTS par les clients, et non codés en dur. Changer un tel URI ne devrait pas être considéré comme un changement incompatible. Le nouvel URI peut remplacer l'ancien et les clients pourront redécouvrir l'URI et continuer à fonctionner.

Il convient de noter cependant que, si l’utilisation des identificateurs de version dans l’URI est problématique pour toutes ces raisons,it is not un-RESTful en aucune façon.

6. Conclusion

Cet article a tenté de donner un aperçu du problème très diversifié et difficile desevolving a REST Service. Nous avons discuté des deux solutions communes, avantages et inconvénients de chacune, et des moyens de raisonner sur ces approches dans le contexte de REST.

L'article conclut en présentant le cas de la deuxième solution -versioning the media types tout en examinant les modifications possibles d'une API RESTful.

L'implémentation complète de ce didacticiel se trouve dansGitHub project.

7. Lectures complémentaires

Habituellement, ces ressources de lecture sont liées tout au long de l'article, mais dans ce cas, il y en a tout simplement trop: