From dd62cf9d48c7e95ab1b456d5f6c993ea5dd5f284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20DERUETTE?= Date: Fri, 15 Nov 2024 21:38:17 +0100 Subject: [PATCH] =?UTF-8?q?[Core]=20G=C3=A9rer=20les=20erreurs=20d'API=20s?= =?UTF-8?q?elon=20la=20norme=20RFC=207807=20Fix=20#207?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/network/error-parsing.ts | 62 ++++++++++++++++++++-- packages/core/src/network/fetch.ts | 5 +- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/packages/core/src/network/error-parsing.ts b/packages/core/src/network/error-parsing.ts index 4646f0717..832e43146 100644 --- a/packages/core/src/network/error-parsing.ts +++ b/packages/core/src/network/error-parsing.ts @@ -1,14 +1,51 @@ import {messageStore} from "../stores/message"; -/** Format attendu des erreurs JSON issues du serveur. */ -export interface ErrorResponse { - [key: string]: any; +export interface ProblemDetail { + /** + * @description A URI reference [RFC3986] that identifies the problem type. + * This specification encourages that, when dereferenced, it provide human-readable documentation + * for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). + * When this member is not present, its value is assumed to be "type" (string) - "about:blank". + */ + type?: string | "about:blank"; + + /** + * @description (number) - The HTTP status code ([RFC7231], Section 6) + * generated by the origin server for this occurrence of the problem. + */ status: number; + + /** + * @description A short, human-readable summary of the problem + * type. It SHOULD NOT change from occurrence to occurrence of the + * problem, except for purposes of localization (e.g., using + * proactive content negotiation; see [RFC7231], Section 3.4). + */ + title?: string; + + /** + * @description A human-readable explanation specific to + * this occurrence of the problem. + */ + detail?: string; + + /** + * @description A URI reference that identifies the specific occurrence of the problem. + * It may or may not yield further information if dereferenced. + */ + instance?: string; + + /** + * @description Problem type definitions MAY extend the problem details object with additional members. + */ + [key: string]: any; } +/** Format attendu des erreurs JSON issues du serveur. */ +export interface ErrorResponse extends ProblemDetail {} + /** Erreur JSON issue du serveur, à laquelle on a ajouté des infos issues du parsing. */ -export interface ManagedErrorResponse { - [key: string]: any; +export interface ManagedErrorResponse extends ErrorResponse { /** Erreurs détectées dans l'erreur serveur. */ $parsedErrors: { /** Erreurs globales. */ @@ -32,3 +69,18 @@ export function manageResponseErrors($status: number, response: ErrorResponse): } }; } + +/** + * Parse une réponse du serveur pour enregistrer les erreurs. + * @param $status Statut HTTP de la réponse. + * @param response Corps de la réponse. + */ +export function manageProblemDetail(response: ProblemDetail): ManagedErrorResponse { + return { + ...response, + $status: response.status, + $parsedErrors: { + globals: messageStore.addMessages(response) + } + }; +} diff --git a/packages/core/src/network/fetch.ts b/packages/core/src/network/fetch.ts index 03ce98b7e..1706cc779 100644 --- a/packages/core/src/network/fetch.ts +++ b/packages/core/src/network/fetch.ts @@ -3,7 +3,7 @@ import {isObject, merge, toPairs} from "lodash"; import {config} from "../utils"; -import {ManagedErrorResponse, manageResponseErrors} from "./error-parsing"; +import {ManagedErrorResponse, manageProblemDetail, manageResponseErrors} from "./error-parsing"; import {HttpMethod, requestStore} from "./store"; /** @@ -77,6 +77,9 @@ export async function coreFetch( return await Promise.reject( manageResponseErrors(response.status, await response.json()) ); + } else if (contentType?.includes("application/problem+json")) { + // Pour une erreur JSON, on la parse pour trouver et enregistrer les erreurs "attendues". + return await Promise.reject(manageProblemDetail(await response.json())); } else { // Sinon, on renvoie le body de la réponse sous format texte (faute de mieux). console.error(`Une erreur ${response.status} est survenue lors de l'appel à "${url}".`);