web-dev-qa-db-fra.com

REST versioning api (version uniquement la représentation, pas la ressource elle-même)

J'ai jeté un coup d'œil à Meilleures pratiques pour le contrôle de version d'API? , mais je ne suis pas tout à fait convaincu de la réponse, donc je remets en question la partie de contrôle de version avec un exemple plus spécifique. J'ai deux URI (un avec versioning faisant partie de l'URI et un sans):

http://xxxx/v1/user/123    -> favored solution in discussed thread
http://xxxx/user/123             

Je doute que le premier lien exprime l'idée de REST. Je trouve http://xxxx/v1/user/123 déroutant car cela suggère qu'il y aura un jour une version api supérieure comme http://xxxx/v2/user/123. Mais cela n'a pas de sens en termes REST, la version api elle-même est HTTP 1.0 ou 1.1, qui est déjà envoyée dans la requête HTTP. Cette ressource REST la vue centrée diffère très des autres interfaces api comme SOAP ou interfaces Java (où il est courant d'avoir des versions api dans des noms qualifiés).

À REST la seule chose où le contrôle de version est logique est la représentation de cette ressource (par exemple, de nouveaux champs sont ajoutés ou supprimés). Ce contrôle de version fait partie de la négociation de contenu comme:

http://xxx/user/123 + HTTP 'Accept' Header -> Content negotation through header
http://xxx/user/123?v=1                    -> for perma-links/hyperlinks

On pourrait également affirmer qu'une telle négociation de contenu de version pourrait faire partie de l'URI à l'intérieur du chemin, mais je le trouve contre-intuitif, car vous pourriez vous retrouver avec différents URI pour la même ressource et devoir maintenir des redirections à un moment donné.

Pour résumer: Dans REST il n'y a pas de version api, seulement la version de la représentation de la ressource. La représentation version-info appartient à la négociation de contenu (comme queryParam ou HTTP 'Accept').

Qu'est-ce que tu penses? Sur quels points seriez-vous en désaccord/d'accord?

51
manuel aldana

Je suis complètement d'accord; un URI exprime l'identité, l'identité ne change pas lorsqu'une nouvelle version est introduite. Il pourrait y avoir de nouveaux URI pour des concepts supplémentaires, bien sûr, et les URI existants pourraient rediriger… mais l'inclusion d'un "v2" dans l'URI me fait sentir RPCish.

Notez que cela n'a rien à voir avec REST, vraiment, car d'un point de vue REST ce ne sont que des caractères.

36
Stefan Tilkov

Vous pourriez écouter un X-API-Version En-tête de requête HTTP. Si l'en-tête existe, le serveur doit utiliser cette version de l'API. Si l'en-tête n'existe pas, le serveur peut utiliser la dernière version de l'API.

> GET /user/123 HTTP/1.1
> Host: xxx
> X-API-Version: >=1.5.1, <2.0.0
> Accept: application/json
>

< HTTP/1.1 200 OK
< X-API-Version: 1.6.12
<
< { "user": { "id": 123, "name": "Bob Smith" } }
<
10
yfeldblum

Pour ce que ça vaut, je suis d'accord avec toi Manuel. Vous pouvez voir mon raisonnement dans cette question Comment version REST URIs

Il y a beaucoup de gens qui semblent être en désaccord mais je ne m'inquiéterais pas. À quoi ressemble votre URL n'a vraiment pas un grand impact sur votre client tant que vous respectez la contrainte hypertexte.

9
Darrel Miller

Je suis d'accord que vous ne voulez pas voir les versions dans les URI des ressources présentées dans votre API. Cela ne les rend pas "cool". Conviennent également que ce sont les représentations qui sont les plus susceptibles de changer.

Cependant, cela soulève alors la question de ce qui se passe lorsque vous modifiez le contenu d'une représentation particulière. Par exemple, si votre représentation JSON originale d'un frobnitz est

{"x": "bam", "y": "hello"}

et si vous souhaitez ajouter un champ "z", vous pouvez penser que le client devrait être conscient que nous sommes maintenant sur la version 2 d'une sorte de schéma de données.

Je ne suis pas certain de ça. Je pense que vous avez quelques options:

  • Rendez vos clients flexibles face à une représentation en légère évolution. Dans l'exemple ci-dessus, nous générons toujours un dictionnaire JSON.
  • Si vous devez, mettez une version dans la représentation elle-même (un champ de version dans cet exemple). Ce faisant, vous déclarez effectivement une sous-représentation dans le type de contenu JSON. Je pense que c'est assez limitatif.
  • Utilisez vos propres types MIME et versionnez-les: application/x-my-special-json1.0, application/x-my-special-json1.1. Cela vous permet de versionner vos représentations indépendamment les unes des autres. Encore une fois, avec celui-ci, vous demandez à vos clients de savoir ce qui se passe.

En général, je pense que vous souhaitez optimiser votre API et vos représentations pour des clients que vous n'avez pas inventés vous-même; ceux que d'autres créeront en découvrant vos ressources. Je crois que cela est utile même dans le cas où vous créez quelque chose qui est privé, car il intègre une contrainte de conception utile qui contribuera à rendre votre système plus robuste.

2
cdent

Une autre approche pourrait être de dire que "une représentation a plusieurs API":

http://xxx/user/123/api/1.json

Et si vous le souhaitez, vous pouvez retourner la représentation en utilisant la dernière API lors d'une demande comme celle-ci:

http://xxx/user/123.json

Personnellement, j'aime mieux les autres solutions, mais c'est une autre approche que je n'ai pas encore suggérée ici.

1
MPV

Je trouve http: // xxxx/v1/user/12 déroutant car cela suggère qu'il y aura un jour une version api supérieure comme http: // xxxx/v2/user/12

Cela ne suggère pas que - mais vous ayez cette capacité à l'avenir.

Mais cela n'a pas de sens en termes REST, la version api elle-même est HTTP 1.0 ou 1.1, qui est déjà envoyée dans la requête HTTP.

La version de VOTRE API et la version de HTTP que vous utilisez pour effectuer des demandes ne doivent pas nécessairement être égales.

On pourrait également affirmer qu'une telle négociation de contenu de version pourrait faire partie de l'URI à l'intérieur du chemin, mais je le trouve contre-intuitif, car vous pourriez vous retrouver avec différents URI pour la même ressource et devoir maintenir des redirections à un moment donné.

C'est correct d'avoir la version comme paramètre URI comme vous l'avez démontré.

http: // xxx/user/123? v = 1 -> pour perma-links/hyperlinks

1
mr-sk

Pour REST, ce que la plupart des réponses oublient, c'est l'élément de données. Je suppose que plusieurs API de version partagent toujours la même couche de données. Cela signifie que la couche de données vous oblige à penser de manière rétrocompatible. Les changements importants qui doivent être effectués ne sont possibles que si votre API change de manière rétrocompatible. En pratique, cela signifie que des propriétés supplémentaires sont ajoutées silencieusement à vos entités lors de l'utilisation de la dépréciation par date dans votre document API pour indiquer quand quelque chose sera supprimé. Idéalement, vous utilisez un système d'enregistrement avec l'adresse e-mail de vos utilisateurs de clés API, afin de pouvoir les informer de la dépréciation dans une certaine portée (à la Facebook) .Par conséquent, je ne pense pas que vous ayez besoin de spécifier une version n'importe où.

0
Pepster