Question Bonnes pratiques pour le versioning de l'API [fermé]


Existe-t-il des procédures ou des pratiques recommandées pour le versioning de l'API REST du service Web?

J'ai remarqué que AWS effectue la gestion des versions par l'URL du point de terminaison. Est-ce le seul moyen ou existe-t-il d'autres moyens d'atteindre le même objectif? S'il y a plusieurs façons, quels sont les mérites de chaque façon?


878
2017-12-23 15:32


origine


Réponses:


C'est une bonne question et une question délicate. Le sujet de La conception de l'URI est en même temps la partie la plus importante d'une API REST etdonc un potentiel engagement à long terme envers les utilisateurs de cette API.

Depuis l'évolution d'une application et, dans une moindre mesure, de son API est une réalité de la vie et qu'il est même similaire à l'évolution d'un produit apparemment complexe comme un langage de programmation, le Conception d'URI devrait avoir moins contraintes naturelles et cela devrait être préservé au fil du temps. Plus la durée de vie de l'application et de l'API est longue, plus l'engagement envers les utilisateurs de l'application et de l'API est grand.

D'autre part, un autre fait de la vie est qu'il est difficile de prévoir toutes les ressources et leurs aspects qui seraient consommés à travers l'API. Heureusement, il n'est pas nécessaire de concevoir l'API entière qui sera utilisée jusqu'à apocalypse. Il suffit de définir correctement tous les points d'extrémité de ressource et le schéma d'adressage de chaque ressource et instance de ressource.

Au fil du temps, vous devrez peut-être ajouter de nouvelles ressources et de nouveaux attributs à chaque ressource particulière, mais la méthode que les utilisateurs de l'API suivent pour accéder à des ressources particulières ne doit pas changer une fois que le système d'adressage devient public.

Cette méthode s'applique à la sémantique des verbes HTTP (par exemple PUT doit toujours être mise à jour / remplacer) et aux codes d'état HTTP pris en charge dans les versions antérieures de l'API (ils devraient continuer à fonctionner) afin que les clients API puissent continuer à travailler. comme ça).

De plus, l'incorporation de la version de l'API dans l'URI perturberait le concept de hypermédia comme moteur de l'état de l'application (déclaré dans la thèse de doctorat Roy T. Fieldings) en ayant une adresse de ressource / URI qui changerait au fil du temps, je voudrais conclure que Les versions de l'API ne doivent pas être conservées longtemps dans les URI de ressources ce qui signifie que URI de ressources sur lesquelles les utilisateurs de l'API peuvent compter devraient être des liens permanents.

Sûr, il est possible d'intégrer la version de l'API dans l'URI de base mais uniquement pour des utilisations raisonnables et restreintes comme le débogage d'un client API cela fonctionne avec la nouvelle version de l'API. De telles API versionnées doivent être limitées dans le temps et disponibles pour des groupes limités d'utilisateurs d'API (par exemple, pendant les bêtas fermés). Sinon, vous vous engagez où vous ne devriez pas.

Quelques réflexions concernant la maintenance des versions de l'API qui ont une date d'expiration. Toutes les plates-formes / langages de programmation couramment utilisés pour implémenter des services Web (Java, .NET, PHP, Perl, Rails, etc.) permettent une liaison facile des points d'extrémité de service Web vers un URI de base. De cette façon, il est facile de rassemble et garde une collection de fichiers / classes / méthodes séparer entre différentes versions de l'API.

A partir du POV des utilisateurs de l'API, il est également plus facile de travailler avec et de lier une version particulière de l'API lorsque cela est évident, mais seulement pour un temps limité, c'est-à-dire pendant le développement.

À partir du POV du responsable de l'API, il est plus facile de gérer différentes versions d'API en parallèle en utilisant des systèmes de contrôle de source qui fonctionnent principalement sur les fichiers comme la plus petite unité de version (code source).

Cependant, avec les versions d'API clairement visibles dans l'URI, il y a une mise en garde: on pourrait aussi objecter cette approche depuis L'historique de l'API devient visible / transparent dans la conception de l'URI  et est donc sujet à des changements au fil du temps ce qui va à l'encontre des lignes directrices de REST. Je suis d'accord!

La façon de contourner cette objection raisonnable est d'implémenter la dernière version de l'API sous URI de base de l'API sans version. Dans ce cas, les développeurs de client API peuvent choisir entre:

  • développer par rapport à la dernière (en s'engageant à maintenir l'application en la protégeant des éventuelles modifications de l'API susceptibles de casser leur client API mal conçu).

  • lier à une version spécifique de l'API (qui devient apparente) mais seulement pour un temps limité

Par exemple, si l'API v3.0 est la dernière version de l'API, les deux suivants doivent être des alias (c'est-à-dire se comporter de manière identique à toutes les demandes d'API):

http: // shonzilla / api / clients / 1234
http: // shonzilla / api/v3.0/ clients / 1234
http: // shonzilla / api/ v3/ clients / 1234

En outre, les clients API qui tentent toujours de pointer vers le vieux L'API doit être informée de l'utilisation de la dernière version précédente de l'API, si la version de l'API qu'ils utilisent est obsolète ou n'est plus supportée. Donc, accéder à l'un des URI obsolètes comme ceux-ci:

http: // shonzilla / api/v2.2/ clients / 1234
http: // shonzilla / api/v2.0/ clients / 1234
http: // shonzilla / api/ v2/ clients / 1234
http: // shonzilla / api/v1.1/ clients / 1234
http: // shonzilla / api/ v1/ clients / 1234

devrait retourner l'un des 30 codes d'état HTTP indiquant la redirection qui sont utilisés en conjonction avec Location En-tête HTTP qui redirige vers la version appropriée de l'URI de ressource qui reste à être celle-ci:

http: // shonzilla / api / clients / 1234

Il existe au moins deux codes d'état HTTP de redirection appropriés pour les scénarios de versionnement de l'API:

  • 301 Déménagé Définitivement indiquant que la ressource avec un URI demandé est déplacée définitivement vers un autre URI (qui devrait être un lien permanent d'instance de ressource qui ne contient pas d'information sur la version de l'API). Ce code d'état peut être utilisé pour indiquer une version de l'API obsolète / non prise en charge, informant le client API qu'un l'URI de ressource versionnée a été remplacée par un permalien de ressource.

  • 302 trouvé indiquant que la ressource demandée est temporairement située à un autre emplacement, alors que l'URI demandée peut toujours être prise en charge. Ce code d'état peut être utile lorsque les URI sans version sont temporairement indisponibles et qu'une demande doit être répétée en utilisant l'adresse de redirection (par exemple en pointant vers l'URI avec la version APi intégrée) et nous voulons dire aux clients de continuer à l'utiliser. permaliens).

  • d'autres scénarios peuvent être trouvés dans Redirection du chapitre 3xx de la spécification HTTP 1.1


684
2017-12-29 20:24



L'URL ne doit PAS contenir les versions. La version n'a rien à voir avec "l'idée" de la ressource que vous demandez. Vous devriez essayer de penser à l'URL comme étant un chemin vers le concept que vous souhaitez - pas comment vous voulez que l'élément soit retourné. La version dicte la représentation de l'objet, pas le concept de l'objet. Comme d'autres affiches l'ont dit, vous devriez spécifier le format (y compris la version) dans l'en-tête de la demande.

Si vous regardez la requête HTTP complète pour les URL qui ont des versions, cela ressemble à ceci:

(BAD WAY TO DO IT):

http://company.com/api/v3.0/customer/123
====>
GET v3.0/customer/123 HTTP/1.1
Accept: application/xml

<====
HTTP/1.1 200 OK
Content-Type: application/xml
<customer version="3.0">
  <name>Neil Armstrong</name>
</customer>

L'en-tête contient la ligne qui contient la représentation que vous demandez ("Accept: application / xml"). C'est là que la version devrait aller. Tout le monde semble oublier le fait que vous pouvez vouloir la même chose dans différents formats et que le client devrait pouvoir demander ce qu'il veut. Dans l'exemple ci-dessus, le client demande TOUT Représentation XML de la ressource - pas vraiment la vraie représentation de ce qu'elle veut. Le serveur pourrait, en théorie, retourner quelque chose de complètement sans rapport avec la requête tant que c'était du XML et il faudrait l'analyser pour se rendre compte que c'est faux.

Une meilleure façon est:

(GOOD WAY TO DO IT)

http://company.com/api/customer/123
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+xml

<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+xml
<customer>
  <name>Neil Armstrong</name>
</customer>

De plus, disons que les clients pensent que le XML est trop verbeux et qu'ils veulent maintenant du JSON à la place. Dans les autres exemples, vous devriez avoir une nouvelle URL pour le même client, de sorte que vous vous retrouveriez avec:

(BAD)
http://company.com/api/JSONv3.0/customers/123
  or
http://company.com/api/v3.0/customers/123?format="JSON"

(ou quelque chose de similaire). En fait, chaque requête HTTP contient le format que vous recherchez:

(GOOD WAY TO DO IT)
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+json

<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+json

{"customer":
  {"name":"Neil Armstrong"}
}

En utilisant cette méthode, vous avez beaucoup plus de liberté dans la conception et adhérez en fait à l'idée originale de REST. Vous pouvez modifier les versions sans perturber les clients ou modifier les clients de manière incrémentielle à mesure que les API sont modifiées. Si vous choisissez d'arrêter de prendre en charge une représentation, vous pouvez répondre aux demandes avec un code d'état HTTP ou des codes personnalisés. Le client peut également vérifier que la réponse est dans le bon format et valider le XML.

Il y a beaucoup d'autres avantages et j'en discute ici sur mon blog:    http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html

Un dernier exemple pour montrer comment mettre la version dans l'URL est mauvaise. Disons que vous voulez un morceau d'information à l'intérieur de l'objet, et vous avez versionné vos différents objets (les clients sont v3.0, les commandes sont v2.0, et l'objet shipto est v4.2). Voici la mauvaise URL que vous devez fournir dans le client:

(Another reason why version in the URL sucks)
http://company.com/api/v3.0/customer/123/v2.0/orders/4321/

273
2017-07-19 16:08



Nous avons trouvé pratique et utile de mettre la version dans l'URL. Il est facile de dire ce que vous utilisez en un coup d'œil. Nous faisons des alias / foo à / foo / (dernières versions) pour faciliter l'utilisation, des URL plus courtes / plus propres, etc., comme le suggère la réponse acceptée.

Rester rétrocompatible pour toujours est souvent prohibitif et / ou très difficile. Nous préférons donner un préavis de dépréciation, des redirections comme suggéré ici, docs, et d'autres mécanismes.


99
2018-01-04 20:57



Je suis d'accord que la version de la représentation des ressources suit mieux l'approche REST ... mais, un gros problème avec les types MIME personnalisés (ou les types MIME qui ajoutent un paramètre de version) est le mauvais support pour écrire dans les en-têtes Accept et Content-Type. JavaScript.

Par exemple, il n'est pas possible que IMO à POST avec les en-têtes suivants dans les formulaires HTML5, afin de créer une ressource:

Accept: application/vnd.company.myapp-v3+json
Content-Type: application/vnd.company.myapp-v3+json 

C'est parce que le HTML5 enctype attribut est une énumération, donc tout autre que l'habituel application/x-www-formurlencoded, multipart/form-data et text/plain sont invalides.

... et je ne suis pas sûr qu'il est supporté par tous les navigateurs HTML4 (qui a un attribut plus lax, mais serait un problème d'implémentation du navigateur si le type MIME a été transféré)

Pour cette raison, je pense maintenant que la façon la plus appropriée d'utiliser la version est via l'URI, mais je reconnais que ce n'est pas la bonne façon.


46
2017-10-13 10:51



Mettez votre version dans l'URI. Une version d'une API ne supporte pas toujours les types d'une autre, donc l'argument selon lequel les ressources sont simplement migrées d'une version à l'autre est tout simplement faux. Ce n'est pas la même chose que de passer du format XML au format JSON. Les types peuvent ne pas exister, ou ils peuvent avoir changé sémantiquement.

Les versions font partie de l'adresse de la ressource. Vous acheminez d'une API à une autre. Ce n'est pas RESTful de cacher l'adressage dans l'en-tête.


21
2018-06-05 15:09



Il existe quelques endroits où vous pouvez effectuer des versions dans une API REST:

  1. Comme indiqué, dans l'URI. Cela peut être traitable et même esthétiquement agréable si les redirections et similaires sont bien utilisés.

  2. Dans l'en-tête Accepts:, la version est dans le type de fichier. Comme 'mp3' vs 'mp4'. Cela fonctionnera également, bien que l'OMI fonctionne un peu moins bien que ...

  3. Dans la ressource elle-même. De nombreux formats de fichiers ont leurs numéros de version intégrés, généralement dans l'en-tête; Cela permet aux logiciels les plus récents de «fonctionner» en comprenant toutes les versions existantes du type de fichier alors que les logiciels plus anciens peuvent le faire si une version non prise en charge (plus récente) est spécifiée. Dans le contexte d'une API REST, cela signifie que vos URI ne doivent jamais changer, juste votre réponse à la version particulière des données que vous avez reçues.

Je peux voir des raisons d'utiliser les trois approches:

  1. si vous aimez faire de nouvelles API «clean sweep», ou pour les changements majeurs de version où vous voulez une telle approche.
  2. Si vous voulez que le client sache avant de faire un PUT / POST si ça va marcher ou non.
  3. si c'est bon si le client doit faire son PUT / POST pour savoir si ça va marcher.

13
2017-10-24 16:39



La version de votre API REST est analogue à la version de n'importe quelle autre API. Des modifications mineures peuvent être effectuées, des modifications majeures peuvent nécessiter une nouvelle API complète. Le plus simple pour vous est de recommencer à zéro à chaque fois, c'est-à-dire lorsque la mise à jour de la version dans l'URL est la plus logique. Si vous voulez faciliter la vie du client, vous essayez de maintenir la rétrocompatibilité, ce que vous pouvez faire avec la dépréciation (redirection permanente), les ressources dans plusieurs versions, etc. C'est plus compliqué et cela demande plus d'efforts. Mais c'est aussi ce que REST encourage à "Les URIs cool ne changent pas".

En fin de compte, c'est comme n'importe quel autre design d'API. Peser l'effort contre la commodité du client. Envisagez d'adopter un versionnage sémantique pour votre API, ce qui permet à vos clients de voir à quel point votre nouvelle version est compatible.


8
2018-03-06 07:16