1 points par GN⁺ 4 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Lorsqu'une API web publique utilise à la fois un nom comme Product API et un chemin /api/v1, la version sémantique de l'API et sa structure peuvent se désaligner
  • Faire coexister un chemin /v1/ et major.minor.patch mélange les routes et le contrat d'API, et fige le premier chiffre de la version sémantique dans l'URL
  • Les changements cassant la compatibilité nécessitent un nouveau chemin et des routes de reverse proxy, ce qui peut disperser les informations de contrat entre l'URL et le numéro de version
  • Si des API ultérieures sont créées en parallèle, l'API existante se retrouve de fait liée à v1, et lors de futurs changements incompatibles, le sens du nom et du chemin devient ambigu
  • Il s'agit d'une réflexion visant à identifier, dans le versioning des API web publiques, des pratiques répétitivement frustrantes et de meilleurs principes de conception

1 commentaires

 
GN⁺ 4 시간 전
Avis sur Lobste.rs
  • Mettre /v1/ dans l’URL a en fait un gros avantage : cela force à ne pas casser l’API pour les utilisateurs tant que l’endpoint n’est pas désactivé

  • D’autres articles du même auteur, comme Evolving HTTP APIs, donnent des conseils utiles

  • En général, on ajoute /v1/, /v2/, etc. à chaque route pour signaler les changements cassants. S’il s’agit d’une API publique exploitée en production, et non d’une norme destinée à fonctionner sur plusieurs hôtes, il y a peu de raisons d’appliquer un versionnement sémantique complet (semantic versioning)
    Le versionnement sémantique existe pour permettre à d’autres développeurs de mettre à jour leurs dépendances avec confiance, sans passer 20 minutes à lire le changelog, alors que sur une API en production les gens ne peuvent pas choisir quand adopter une nouvelle version mineure ou correctrice
    On considère généralement comme changement cassant le fait de modifier un comportement documenté ou de casser des clients existants qui dépendent de ce comportement documenté. Certains considèrent aussi qu’un changement de comportement non documenté est cassant, mais cela comporte beaucoup de risques

  • Chez Google, ils font comme ça : AIP-185: API Versioning, AIP-180: Bacwards compatibility
    J’ai l’impression que ces documents de conception sont assez spécifiques à la manière de travailler chez Google, mais je m’y suis référé pour concevoir des API et certaines idées qu’ils contiennent étaient très utiles

  • En règle générale, je pense que toutes les API devraient chercher à minimiser autant que possible les changements cassants. Par exemple, si l’on veut renommer une propriété, il vaut mieux ajouter le nouveau nom en doublon plutôt que supprimer l’ancienne propriété
    Cela dit, l’approche the people at Buttondown do it est aussi élégante. Ils définissent des migrations entre versions d’API, ce qui permet aux consommateurs d’épingler leur version d’API via un header, tandis que le fournisseur peut continuer à faire évoluer l’ensemble

    • Dupliquer les propriétés en sortie a plutôt bien fonctionné. En revanche, pour les entrées, il faut gérer le cas où le client envoie les deux propriétés avec des valeurs différentes
      On pense spontanément à répondre « le nouveau nom a toujours la priorité », mais cela peut échouer si le client suit une séquence lecture-modification-écriture et renvoie une version modifiée d’un objet créé par le serveur. Le client peut mettre à jour uniquement l’ancienne propriété et renvoyer telle quelle la nouvelle propriété, qu’il a ignorée
    • Comme l’a expliqué ce fournisseur d’API, proposer des migrations entre versions d’API semble une bonne idée, mais utiliser un header de requête HTTP pour le versionnement peut poser problème
    • Ce lien explique très bien comment traiter la forme des données. Mais ce n’est qu’une partie du sujet, et je me demande comment gérer les cas où le comportement lui-même change
      On pourrait sans doute appliquer ce type de transformation à l’aiguillage du comportement aussi, mais sauf erreur de ma part ce point n’était pas abordé
  • Dans l’idéal, il faut inclure la version dans le chemin, et faire en sorte que les nouvelles versions soient additives. Ainsi, l’API d’une ancienne version peut rerouter les requêtes vers une version plus récente après les transformations d’entrée/sortie nécessaires
    Quelques années plus tard, si plus personne n’utilise une ancienne version, on peut la supprimer, et le chemin /v1/ devient une erreur

  • J’ai déjà un peu lu sur le versionnement d’API via la négociation de contenu avec le header Accept. Si quelqu’un a déjà pratiqué le versionnement d’API de cette manière, son retour d’expérience m’intéresse
    D’après mon expérience, le versionnement par ressource ou le versionnement global reste ce qu’il y a de plus intuitif. Pour la dépréciation, une combinaison du header de réponse HTTP Deprecation (RFC 9745) puis, à terme, d’une réponse comme 410 Gone sur les anciens endpoints, me semble une manière raisonnable d’amener les clients à migrer vers la nouvelle version
    En plus, je serais vraiment curieux de savoir si quelqu’un a déjà construit une API évolutive : une API qui traduit en interne les requêtes d’anciennes versions vers celles d’une version plus récente, puis supprime réellement l’ancienne version une fois que les clients ont migré ou qu’un certain délai s’est écoulé