3. The Problem Details JSON Object (L'objet JSON de détails de problème)
Le modèle canonique pour les détails de problème est un objet JSON [JSON]. Lorsqu'il est sérialisé dans un document JSON, ce format est identifié avec le type de média "application/problem+json".
Par exemple:
POST /purchase HTTP/1.1
Host: store.example.com
Content-Type: application/json
Accept: application/json, application/problem+json
{
"item": 123456,
"quantity": 2
}
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345",
"/account/67890"]
}
Ici, le problème out-of-credit (identifié par son type) indique la raison du 403 dans "title", identifie l'occurrence spécifique du problème avec "instance", donne des détails spécifiques à l'occurrence dans "detail", et ajoute deux extensions: "balance" transmet le solde du compte, et "accounts" liste les liens où le compte peut être rechargé.
Lorsqu'elles sont conçues pour l'accommoder, les extensions spécifiques au problème peuvent transmettre plus d'une instance du même type de problème. Par exemple:
POST /details HTTP/1.1
Host: account.example.com
Accept: application/json
{
"age": 42.3,
"profile": {
"color": "yellow"
}
}
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.net/validation-error",
"title": "Your request is not valid.",
"errors": [
{
"detail": "must be a positive integer",
"pointer": "#/age"
},
{
"detail": "must be 'green', 'red' or 'blue'",
"pointer": "#/profile/color"
}
]
}
Le type de problème fictif ici définit l'extension "errors", un tableau qui décrit les détails de chaque erreur de validation. Chaque membre est un objet contenant "detail" pour décrire le problème et "pointer" pour localiser le problème dans le contenu de la requête en utilisant un JSON Pointer [JSON-POINTER].
Lorsqu'une API rencontre plusieurs problèmes qui ne partagent pas le même type, il est RECOMMANDÉ que le problème le plus pertinent ou urgent soit représenté dans la réponse. Bien qu'il soit possible de créer des types de problèmes "batch" génériques qui transmettent plusieurs types disparates, ils ne s'adaptent pas bien aux sémantiques HTTP.
Notez également que l'API a répondu avec le type "application/problem+json", même si le client ne l'a pas listé dans Accept, comme le permet HTTP (voir section 12.5.1 de [HTTP]).
3.1. Members of a Problem Details Object (Membres d'un objet de détails de problème)
Les objets de détails de problème peuvent avoir les membres suivants. Si le type de valeur d'un membre ne correspond pas au type spécifié, le membre DOIT être ignoré -- c'est-à-dire que le traitement continuera comme si le membre n'avait pas été présent.
3.1.1. "type"
Le membre "type" est une chaîne JSON contenant une référence URI [URI] qui identifie le type de problème. Les consommateurs DOIVENT utiliser l'URI "type" (après résolution, si nécessaire) comme identifiant principal du type de problème.
Lorsque ce membre n'est pas présent, sa valeur est supposée être "about:blank".
Si l'URI de type est un localisateur (par exemple, ceux avec un schéma "http" ou "https"), le déréférencer DEVRAIT fournir une documentation lisible par l'homme pour le type de problème (par exemple, en utilisant HTML [HTML5]). Cependant, les consommateurs NE DEVRAIENT PAS déréférencer automatiquement l'URI de type, à moins qu'ils ne le fassent lorsqu'ils fournissent des informations aux développeurs (par exemple, lorsqu'un outil de débogage est utilisé).
Lorsque "type" contient un URI relatif, il est résolu par rapport à l'URI de base du document, conformément à [URI], section 5. Cependant, l'utilisation d'URI relatifs peut causer de la confusion, et ils peuvent ne pas être traités correctement par toutes les implémentations.
Par exemple, si les deux ressources "https://api.example.org/foo/bar/123" et "https://api.example.org/widget/456" répondent toutes deux avec un "type" égal à la référence URI relative "example-problem", lorsqu'ils sont résolus, ils identifieront différentes ressources ("https://api.example.org/foo/bar/example-problem" et "https://api.example.org/widget/example-problem", respectivement). Par conséquent, il est RECOMMANDÉ d'utiliser des URI absolus dans "type" lorsque cela est possible et que lorsque des URI relatifs sont utilisés, ils incluent le chemin complet (par exemple, "/types/123").
L'URI de type est autorisé à être un URI non résolvable. Par exemple, le schéma URI tag [TAG] peut être utilisé pour identifier de manière unique les types de problèmes:
tag:[email protected],2021-09-17:OutOfLuck
Cependant, les URI de type résolvables sont encouragés par cette spécification car il pourrait devenir souhaitable de résoudre l'URI à l'avenir. Par exemple, si un concepteur d'API utilisait l'URI ci-dessus et adoptait plus tard un outil qui résout les URI de type pour découvrir des informations sur l'erreur, tirer parti de cette capacité nécessiterait de passer à un URI résolvable, créant une nouvelle identité pour le type de problème et introduisant ainsi un changement breaking.
3.1.2. "status"
Le membre "status" est un nombre JSON indiquant le code de statut HTTP (section 15 de [HTTP]) généré par le serveur d'origine pour cette occurrence du problème.
Le membre "status", s'il est présent, est uniquement consultatif; il transmet le code de statut HTTP utilisé pour la commodité du consommateur. Les générateurs DOIVENT utiliser le même code de statut dans la réponse HTTP réelle, pour s'assurer que le logiciel HTTP générique qui ne comprend pas ce format se comporte toujours correctement. Voir section 5 pour d'autres mises en garde concernant son utilisation.
Les consommateurs peuvent utiliser le membre status pour déterminer quel était le code de statut original utilisé par le générateur lorsqu'il a été modifié (par exemple, par un intermédiaire ou un cache) et lorsque le contenu d'un message persiste sans information HTTP. Le logiciel HTTP générique utilisera toujours le code de statut HTTP.
3.1.3. "title"
Le membre "title" est une chaîne JSON contenant un résumé court et lisible par l'homme du type de problème.
Il NE DEVRAIT PAS changer d'une occurrence à l'autre du problème, sauf pour la localisation (par exemple, en utilisant la négociation de contenu proactive; voir section 12.1 de [HTTP]).
La chaîne "title" est consultative et est incluse uniquement pour les utilisateurs qui ne sont pas conscients et ne peuvent pas découvrir la sémantique de l'URI de type (par exemple, lors de l'analyse de journaux hors ligne).
3.1.4. "detail"
Le membre "detail" est une chaîne JSON contenant une explication lisible par l'homme spécifique à cette occurrence du problème.
La chaîne "detail", si elle est présente, devrait se concentrer sur l'aide au client pour corriger le problème, plutôt que de donner des informations de débogage.
Les consommateurs NE DEVRAIENT PAS analyser le membre "detail" pour obtenir des informations; les extensions sont des moyens plus appropriés et moins sujets aux erreurs pour obtenir de telles informations.
3.1.5. "instance"
Le membre "instance" est une chaîne JSON contenant une référence URI qui identifie l'occurrence spécifique du problème.
Lorsque l'URI "instance" est déréférençable, l'objet de détails de problème peut être récupéré à partir de celui-ci. Il pourrait également retourner des informations sur l'occurrence du problème dans d'autres formats grâce à l'utilisation de la négociation de contenu proactive (voir section 12.5.1 de [HTTP]).
Lorsque l'URI "instance" n'est pas déréférençable, il sert d'identifiant unique pour l'occurrence du problème qui peut avoir une signification pour le serveur mais est opaque pour le client.
Lorsque "instance" contient un URI relatif, il est résolu par rapport à l'URI de base du document, conformément à [URI], section 5. Cependant, l'utilisation d'URI relatifs peut causer de la confusion, et ils peuvent ne pas être traités correctement par toutes les implémentations.
Par exemple, si les deux ressources "https://api.example.org/foo/bar/123" et "https://api.example.org/widget/456" répondent toutes deux avec une "instance" égale à la référence URI relative "example-instance", lorsqu'elles sont résolues, elles identifieront différentes ressources ("https://api.example.org/foo/bar/example-instance" et "https://api.example.org/widget/example-instance", respectivement). Par conséquent, il est RECOMMANDÉ d'utiliser des URI absolus dans "instance" lorsque cela est possible, et que lorsque des URI relatifs sont utilisés, ils incluent le chemin complet (par exemple, "/instances/123").
3.2. Extension Members (Membres d'extension)
Les définitions de types de problèmes PEUVENT étendre l'objet de détails de problème avec des membres supplémentaires qui sont spécifiques à ce type de problème.
Par exemple, notre problème out-of-credit ci-dessus définit deux de ces extensions -- "balance" et "accounts" pour transmettre des informations supplémentaires spécifiques au problème.
De même, l'exemple "validation error" définit une extension "errors" qui contient une liste des occurrences d'erreur individuelles trouvées, avec des détails et un pointeur vers l'emplacement de chacune.
Les clients consommant des détails de problème DOIVENT ignorer toutes les extensions qu'ils ne reconnaissent pas; cela permet aux types de problèmes d'évoluer et d'inclure des informations supplémentaires à l'avenir.
Lors de la création d'extensions, les auteurs de types de problèmes doivent choisir leurs noms avec soin. Pour être utilisés dans le format XML (voir annexe B), ils devront se conformer à la règle Name dans la section 2.3 de [XML].