C'est un très vieux post, mais j'ai rencontré un problème similaire et je voudrais partager mon expérience avec vous.
Je construis une architecture de microservices avec des API de repos. J'ai quelques services GET de repos, ils collectent des données du système principal en fonction des paramètres de la demande.
J'ai suivi les autres documents de conception de l'API et j'ai renvoyé HTTP 404 avec un message d'erreur JSON parfait au client lorsqu'aucune donnée ne correspondait aux conditions de la requête (par exemple, aucun enregistrement n'a été sélectionné).
Lorsqu'il n'y avait aucune donnée à renvoyer au client, j'ai préparé un message JSON parfait avec un code d'erreur interne, etc. pour informer le client de la raison du "Not Found" et il a été renvoyé au client avec HTTP 404. Ce fonctionne bien.
Plus tard, j'ai créé une classe cliente d'API de repos qui est une aide facile pour masquer le code lié à la communication HTTP et j'ai utilisé cet assistant tout le temps lorsque j'ai appelé mes API de repos à partir de mon code.
MAIS j'avais besoin d'écrire du code supplémentaire déroutant juste parce que HTTP 404 avait deux fonctions différentes:
- le vrai HTTP 404 lorsque l'API de repos n'est pas disponible dans l'URL donnée, il est lancé par le serveur d'applications ou le serveur Web sur lequel s'exécute l'application d'API de repos
- le client récupère également HTTP 404 lorsqu'il n'y a pas de données dans la base de données en fonction de la condition where de la requête.
Important: Mon gestionnaire d'erreurs de l'API de repos intercepte toutes les exceptions qui apparaissent dans le service principal, ce qui signifie qu'en cas d'erreur, mon API de repos retourne toujours avec un message JSON parfait avec les détails du message.
Ceci est la 1ère version de ma méthode d'assistance client qui gère les deux réponses HTTP 404 différentes:
public static String getSomething(final String uuid) {
String serviceUrl = getServiceUrl();
String path = "user/" + , uuid);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_UTF8)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
// HTTP 200
return response.readEntity(String.class);
} else {
// confusing code comes here just because
// I need to decide the type of HTTP 404...
// trying to parse response body
try {
String responseBody = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(responseBody, ErrorInfo.class);
// re-throw the original exception
throw new MyException(errorInfo);
} catch (IOException e) {
// this is a real HTTP 404
throw new ServiceUnavailableError(response, requestUrl, httpMethod);
}
// this exception will never be thrown
throw new Exception("UNEXPECTED ERRORS, BETTER IF YOU DO NOT SEE IT IN THE LOG");
}
MAIS , parce que mon client Java ou JavaScript peut recevoir en quelque sorte deux types de HTTP 404, je dois vérifier le corps de la réponse dans le cas de HTTP 404. Si je peux analyser le corps de la réponse, je suis sûr d'avoir récupéré une réponse là où il y avait aucune donnée à renvoyer au client.
Si je ne suis pas en mesure d'analyser la réponse, cela signifie que j'ai récupéré un vrai HTTP 404 du serveur Web (et non de l'application API restante).
C'est tellement déroutant et l'application cliente doit toujours effectuer une analyse supplémentaire pour vérifier la vraie raison de HTTP 404.
Honnêtement, je n'aime pas cette solution. C'est déroutant, il faut tout le temps ajouter du code de connerie supplémentaire aux clients.
Donc, au lieu d'utiliser HTTP 404 dans ces deux scénarios différents, j'ai décidé de faire ce qui suit:
- Je n'utilise plus HTTP 404 comme code HTTP de réponse dans mon application de repos.
- Je vais utiliser HTTP 204 (sans contenu) au lieu de HTTP 404.
Dans ce cas, le code client peut être plus élégant:
public static String getString(final String processId, final String key) {
String serviceUrl = getServiceUrl();
String path = String.format("key/%s", key);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
log(requestUrl);
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_JSON_UTF8)
.header(CustomHttpHeader.PROCESS_ID, processId)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return response.readEntity(String.class);
} else {
String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(body, ErrorInfo.class);
throw new MyException(errorInfo);
}
throw new AnyServerError(response, requestUrl, httpMethod);
}
Je pense que cela gère mieux ce problème.
Si vous avez une meilleure solution, partagez-la avec nous.