web-dev-qa-db-fra.com

Gestion des versions REST API

Après avoir lu beaucoup de documents sur REST la gestion des versions, je pense à la gestion des versions des appels à la place de l'API. Par exemple:

http://api.mydomain.com/callfoo/v2.0/param1/param2/param3
http://api.mydomain.com/verifyfoo/v1.0/param1/param2

au lieu d'avoir d'abord

http://api.mydomain.com/v1.0/callfoo/param1/param2
http://api.mydomain.com/v1.0/verifyfoo/param1/param2

puis aller à 

http://api.mydomain.com/v2.0/callfoo/param1/param2/param3
http://api.mydomain.com/v2.0/verifyfoo/param1/param2

Les avantages que je vois sont:

  • Lorsque les appels changent, je n'ai pas besoin de réécrire tout mon client, mais uniquement les parties affectées par les appels modifiés.
  • Les parties du client qui fonctionnent bien peuvent continuer telles quelles (nous avons beaucoup d'heures de test investies pour nous assurer que les côtés client et serveur sont stables.)
  • Je peux utiliser des redirections permanentes ou non permanentes pour les appels modifiés.
  • La compatibilité ascendante serait un jeu d’enfant car je peux laisser les versions d’appel plus anciennes telles quelles.

Est-ce que je manque quelque chose? S'il vous plaît donnez votre avis.

30
Ram Iyer

C'est une question d'opinion; voici le mien, avec la motivation derrière l'opinion. 

  1. inclure la version dans l'URL.
    Pour ceux qui disent, cela appartient à l'en-tête HTTP, je dis: peut-être. Mais la mise en place de l'URL est la méthode acceptée pour le faire, selon les premiers dirigeants sur le terrain. (Google, Yahoo, Twitter, etc.). C’est ce à quoi les développeurs s’attendent et faire ce qu’ils attendent, c’est-à-dire agir conformément au principe du moindre étonnement, est probablement une bonne idée. Cela ne rend absolument pas "la mise à niveau plus difficile pour les clients". Si le changement d'URL représente en quelque sorte un obstacle pour le développeur d'une application consommatrice, comme suggéré dans une réponse différente, ce développeur doit être licencié.

  2. Ignorer la version mineure
    Il y a beaucoup d'entiers. Tu ne vas pas en manquer. Vous n'avez pas besoin de la décimale ici. Toute modification de la version 1.0 à la version 1.1 de votre API ne devrait en aucun cas casser les clients existants. Il suffit donc d'utiliser les nombres naturels. Si vous aimez utiliser la séparation pour impliquer des modifications plus importantes, vous pouvez commencer par v100, puis par v200, etc., mais même dans ce cas, je pense que YAGNI et c'est excessif. 

  3. Mettez la version la plus à gauche dans l'URI
    Votre modèle comportera probablement plusieurs ressources. Ils doivent tous être versionnés de manière synchronisée. Vous ne pouvez pas avoir des personnes utilisant v1 de la ressource X et v2 de la ressource Y. Cela va casser quelque chose. Si vous essayez de soutenir que cela va créer un cauchemar de maintenance lorsque vous ajoutez des versions, il n'y a de toute façon pas de valeur ajoutée pour le développeur. Donc, http://api.mydomain.com/v1/Resource/12345, où Resource est le type de ressource, et 12345 est remplacé par l'ID de la ressource. 

Vous n'avez pas demandé, mais ... 

  1. Omettre les verbes de votre chemin d'URL
    REST est orienté ressources. Vous avez des choses comme "CallFoo" dans votre chemin d'URL, qui ressemble étrangement à un verbe et non à un nom. C'est faux. Utilisez Force, Luke. Utilisez les verbes de REST: GET PUT POST DELETE, etc. Si vous voulez obtenir la vérification sur une ressource, alors faites GET http://domain/v1/Foo/12345/verification. Si vous voulez le mettre à jour, faites POST /v1/Foo/12345

  2. Mettre les paramètres facultatifs comme paramètres de requête ou de données utiles
    Les paramètres facultatifs ne doivent pas figurer dans le chemin de l'URL (avant le premier point d'interrogation), à moins que vous ne suggériez que ces paramètres facultatifs constituent une ressource autonome. Donc, POST /v1/Foo/12345?action=partialUpdate&param1=123&param2=abc

15
Cheeso

Ne faites aucune de ces choses, car elles insèrent la version dans la structure d'URI, ce qui aura des inconvénients pour vos applications clientes. Leur mise à niveau leur sera plus difficile pour tirer parti des nouvelles fonctionnalités de votre application.

Au lieu de cela, vous devriez mettre à jour vos types de média, pas vos URI. Cela vous donnera une flexibilité maximale et une capacité évolutive. Pour plus d'informations, voir cette réponse J'ai donné une autre question.

4
Brian Kelly

J'aime utiliser le paramètre de type de média de profil:

application/json; profile="http://www.myapp.com/schema/entity/v1"

Plus d'informations:

http://tools.ietf.org/html/rfc6906

http://buzzword.org.uk/2009/draft-inkster-profile-parameter-00.html

3
Matthew Madson

Cela dépend de ce que vous appelez des versions dans votre API. Si vous appelez des versions à différentes représentations (xml, json, etc.) des entités, vous devez utiliser les en-têtes accept ou un en-tête personnalisé. C’est ainsi que http est conçu pour travailler avec des représentations. Il est RESTful car si j'appelle la même ressource en même temps mais en demandant des représentations différentes, les entités renvoyées auront exactement les mêmes informations et structure de propriété, mais avec un format différent, ce type de version est esthétique.

D'autre part, si vous entendez les «versions» comme des modifications de la structure de l'entité, par exemple en ajoutant un champ «age» à l'entité «utilisateur». Ensuite, vous devriez aborder cette question du point de vue des ressources, ce qui est à mon avis l’approche RESTful. Comme décrit par Roy Fielding dans son exposé, une ressource REST est un mappage d'un identifiant à un ensemble d'entités ... Il est donc logique que, lors du changement de structure d'une entité, vous ayez besoin d'une ressource appropriée cela pointe vers cette version. Ce type de version est structurel. 

J'ai fait un commentaire similaire dans: http://codebetter.com/howarddierking/2012/11/09/versioning-restful-services/

Lorsque vous travaillez avec la gestion des versions d’URL, la version doit venir plus tard et pas plus tôt dans l’URL:

GET/DELETE/PUT onlinemall.com/grocery-store/customer/v1/{id}
POST onlinemall.com/grocery-store/customer/v1

Une autre façon de le faire de manière plus propre mais qui pourrait poser problème lors de la mise en œuvre:

GET/DELETE/PUT onlinemall.com/grocery-store/customer.v1/{id}
POST onlinemall.com/grocery-store/customer.v1

En procédant de cette manière, le client peut demander spécifiquement la ressource qu'il souhaite qui correspond à l'entité dont il a besoin. Sans devoir manipuler les en-têtes et les types de supports personnalisés, ce qui est vraiment problématique lors de la mise en œuvre dans un environnement de production.

De plus, le fait d’avoir l’URL en retard dans l’URL permet aux clients d’avoir plus de précision dans le choix des ressources qu’ils souhaitent, même au niveau de la méthode.

Mais l’aspect le plus important du point de vue des développeurs est qu’il n’est pas nécessaire de conserver l’ensemble des mappages (chemins) de chaque version pour toutes les ressources et méthodes. Ce qui est très utile lorsque vous avez beaucoup de sous-ressources (ressources intégrées).

Du point de vue de la mise en œuvre, le fait de disposer du niveau de ressources est très facile à mettre en œuvre, par exemple si vous utilisez Jersey/JAX-RS:

@Path("/customer")
public class CustomerResource {
    ...
    @GET
    @Path("/v{version}/{id}")
    public IDto getCustomer(@PathParam("version") String version, @PathParam("id") String id) {
         return locateVersion(version, customerService.findCustomer(id));
    }
    ...
    @POST
    @Path("/v1")
    @Consumes(MediaType.APPLICATION_JSON)
    public IDto insertCustomerV1(CustomerV1Dto customer) {
         return customerService.createCustomer(customer);
    }

    @POST
    @Path("/v2")
    @Consumes(MediaType.APPLICATION_JSON)
    public IDto insertCustomerV2(CustomerV2Dto customer) {
         return customerService.createCustomer(customer);
    }
...
}

IDto est simplement une interface permettant de renvoyer un objet polymorphe, CustomerV1 et CustomerV2 implémentent cette interface.

1
raspacorp

Facebook vérifie dans l'URL . Je pense que la gestion des versions d’URL est plus propre et plus facile à maintenir dans le monde réel.

.Net facilite la gestion des versions de cette manière:

[HttpPost]
[Route("{version}/someCall/{id}")]
public HttpResponseMessage someCall(string version, int id))
0
RayLoveless