To bardzo stary post, ale napotkałem podobny problem i chciałbym podzielić się z wami moimi doświadczeniami.
Buduję architekturę mikrousług z pozostałymi interfejsami API. Mam niektóre usługi GET odpoczynku, zbierają dane z systemu zaplecza na podstawie parametrów żądania.
Postępowałem zgodnie z pozostałymi dokumentami projektowymi API i odesłałem HTTP 404 z doskonałym komunikatem o błędzie JSON do klienta, gdy nie było danych, które pasowałyby do warunków zapytania (na przykład wybrano rekord zero).
Gdy nie było żadnych danych do wysłania z powrotem do klienta, przygotowałem doskonały komunikat JSON z wewnętrznym kodem błędu itp., Aby poinformować klienta o przyczynie „Nie znaleziono”, i został on odesłany z powrotem do klienta z HTTP 404. działa w porządku.
Później utworzyłem klasę spoczynkowego interfejsu API, która jest łatwym pomocnikiem do ukrycia kodu związanego z komunikacją HTTP i korzystałem z tego pomocnika przez cały czas, gdy dzwoniłem do pozostałych interfejsów API z mojego kodu.
ALE musiałem pisać mylący dodatkowy kod tylko dlatego, że HTTP 404 miał dwie różne funkcje:
- prawdziwy HTTP 404, gdy reszta interfejsu API nie jest dostępna w danym adresie URL, jest on generowany przez serwer aplikacji lub serwer WWW, na którym działa reszta aplikacji interfejsu API
- klient również zwraca HTTP 404, gdy nie ma danych w bazie danych w zależności od warunków zapytania.
Ważne: mój moduł obsługi błędów spoczynkowego interfejsu API przechwytuje wszystkie wyjątki pojawiające się w usłudze zaplecza, co oznacza, że w przypadku każdego błędu mój spoczynkowy interfejs API zawsze zwraca doskonały komunikat JSON ze szczegółami komunikatu.
To jest pierwsza wersja metody pomocniczej mojego klienta, która obsługuje dwie różne odpowiedzi HTTP 404:
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");
}
ALE , ponieważ mój klient Java lub JavaScript może odbierać dwa rodzaje HTTP 404, muszę jakoś sprawdzić treść odpowiedzi w przypadku HTTP 404. Jeśli mogę przeanalizować treść odpowiedzi, to jestem pewien, że otrzymałem odpowiedź tam, gdzie była brak danych do odesłania do klienta.
Jeśli nie jestem w stanie przeanalizować odpowiedzi, oznacza to, że odzyskałem prawdziwy HTTP 404 z serwera WWW (nie z pozostałej aplikacji API).
Jest to tak mylące, że aplikacja kliencka musi zawsze wykonać dodatkowe parsowanie, aby sprawdzić prawdziwy powód HTTP 404.
Szczerze mówiąc nie podoba mi się to rozwiązanie. Jest to mylące, musi cały czas dodawać klientom dodatkowe bzdury.
Zamiast więc używać HTTP 404 w tych dwóch różnych scenariuszach, zdecydowałem, że wykonam następujące czynności:
- Nie używam już HTTP 404 jako kodu HTTP odpowiedzi w mojej pozostałej aplikacji.
- Zamierzam użyć HTTP 204 (bez zawartości) zamiast HTTP 404.
W takim przypadku kod klienta może być bardziej elegancki:
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);
}
Myślę, że to lepiej radzi sobie z tym problemem.
Jeśli masz jakieś lepsze rozwiązanie, udostępnij je nam.