Messages d'erreur structurées pour les API HTTP

Nicolas Fränkel

Nicolas Fränkel

November 2, 2022

Technology

Depuis que j'ai commencé à travailler sur le projet Apache APISIX, j'essaie d'améliorer mes connaissances et ma compréhension des API REST RESTful HTTP. Pour cela, je lis et regarde les sources suivantes :

  • Des livres. Actuellement, je termine API Design Patterns. Attendez-vous à une critique bientôt.
  • YouTube. Je recommande la chaîne d'ErikWilde. Bien que certaines vidéos soient meilleures que d'autres, elles se concentrent toutes sur les API.
  • Les IETF RFCs. La plupart des RFC ne concernent pas les API, mais une personne aimable a compilé une liste de celles qui le sont.

Aujourd'hui, je souhaite présenter la RFC "Problem Details for HTTP APIs", également connue sous le nom de RFC 7807.

Le(s) problème(s)

Les principes REST imposent d'utiliser les statuts HTTP pour communiquer. Pour les erreurs, HTTP définit deux plages : les erreurs client, 4xx, et les erreurs serveur, 5xx.

Imaginez une API bancaire qui vous permet d'effectuer des virements. Elle devrait échouer si vous essayez de transférer plus de fonds que vous n'en avez sur votre compte. Plusieurs codes de statut HTTP peuvent correspondre :

  • 400 Bad Request : Le serveur ne peut pas ou ne veut pas traiter la requête en raison d'une erreur perçue comme étant du côté client.
  • 402 Payment Required : La requête ne peut pas être traitée tant que le client n'a pas effectué un paiement. Cependant, aucune convention d'utilisation standard n'existe, et différentes entités l'utilisent dans d'autres contextes.
  • 409 Conflict : La requête est en conflit avec l'état actuel de la ressource cible.

Voici le premier problème : les codes de statut HTTP ont été spécifiés pour des interactions humain-machine via des navigateurs, et non pour des interactions machine-machine via des API. Par conséquent, choisir un code de statut qui correspond parfaitement au cas d'utilisation est rarement simple. Pour mémoire, Martin Fowler semble favoriser le 409 dans notre cas.

Quel que soit le code de statut, le deuxième problème concerne le payload d'erreur ou, plus précisément, sa structure. La structure n'est pas importante si une seule organisation gère le client et le fournisseur de l'API. Même si une équipe dédiée développe chacun d'eux, ils peuvent s'aligner. Par exemple, imaginez une application mobile qui appelle sa propre API.

Cependant, des problèmes surviennent lorsqu'une équipe décide d'utiliser une API tierce. Le choix de la structure de réponse est alors significatif car il est désormais considéré comme faisant partie d'un contrat : tout changement de la part du fournisseur peut casser les clients. Pire encore, la structure est probablement différente d'un fournisseur à l'autre.

Par conséquent, une structure standardisée de rapport d'erreurs :

  • Fournit une uniformité entre les fournisseurs
  • Augmente la stabilité des API

RFC 7807

RFC 7807 vise à résoudre ce problème en fournissant une structure d'erreur standardisée.

La structure est la suivante :

Structure

La RFC décrit les champs :

  • "type" (string) - Une référence URI [RFC3986] qui identifie le type de problème. Cette spécification encourage à ce que, lorsqu'elle est déréférencée, elle fournisse une documentation lisible par l'homme pour le type de problème (par exemple, en utilisant HTML [W3C.REC-html5-20141028]). Lorsque ce membre n'est pas présent, sa valeur est supposée être "about:blank".
  • "title" (string) - Un résumé court et lisible par l'homme du type de problème. Il NE DOIT PAS changer d'une occurrence à l'autre du problème, sauf pour des raisons de localisation (par exemple, en utilisant la négociation de contenu proactive ; voir [RFC7231, Section 3.4]).
  • "status" (number) - Le ([RFC7231], Section 6) généré par le serveur d'origine pour cette occurrence du problème.
  • "detail" (string) - Une explication lisible par l'homme spécifique à cette occurrence du problème.
  • "instance" (string) - Une référence URI qui identifie l'occurrence spécifique du problème. Elle peut ou non fournir des informations supplémentaires si elle est déréférencée.

-- Membres d'un objet de détails de problème

La RFC propose l'exemple suivant lorsqu'il n'y a pas assez de fonds pour effectuer un virement bancaire.

Exemple RFC

Un exemple

Je vais utiliser une de mes démos existantes comme exemple. La démo met en évidence plusieurs étapes pour faciliter le processus d'évolution de vos API.

À l'étape 6, je veux que les utilisateurs s'inscrivent, donc je limite le nombre d'appels dans une fenêtre de temps s'ils ne sont pas authentifiés. J'ai créé un plugin Apache APISIX dédié pour cela. Une fois que le nombre d'appels a atteint la limite, il retourne :

HTTP/1.1 429 Too Many Requests
Date: Fri, 28 Oct 2022 11:56:11 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.15.0

{"error_msg":"Veuillez vous inscrire sur https:\/\/apisix.org\/register pour obtenir votre token API et profiter d'appels illimités"}

Structurons le message selon la RFC 7807.

Règles RFC 7807

Conclusion

La RFC 7807 n'aide pas seulement les développeurs clients. C'est une aide précieuse pour les implémenteurs d'API car elle fournit des directives rapides pour éviter de réinventer la roue à chaque projet.

Pour aller plus loin :

Publié à l'origine sur A Java Geek le 30 octobre 2022

Tags: