Das ist ein sehr alter Beitrag, aber ich hatte ein ähnliches Problem und möchte meine Erfahrungen mit euch teilen.
Ich erstelle eine Microservice-Architektur mit Rest-APIs. Ich habe einige Rest-GET-Dienste, sie sammeln Daten vom Back-End-System basierend auf den Anforderungsparametern.
Ich habe die restlichen API-Entwurfsdokumente befolgt und HTTP 404 mit einer perfekten JSON-Fehlermeldung an den Client zurückgesendet, wenn keine Daten vorhanden waren, die mit den Abfragebedingungen übereinstimmen (z. B. wurde der Datensatz Null ausgewählt).
Wenn keine Daten an den Client zurückgesendet werden konnten, habe ich eine perfekte JSON-Nachricht mit internem Fehlercode usw. vorbereitet, um den Client über den Grund für "Nicht gefunden" zu informieren, und sie wurde mit HTTP 404 an den Client zurückgesendet funktioniert gut.
Später habe ich eine Rest-API-Client-Klasse erstellt, die ein einfacher Helfer ist, um den HTTP-Kommunikationscode auszublenden, und ich habe diesen Helfer die ganze Zeit verwendet, als ich meine Rest-APIs aus meinem Code heraus aufgerufen habe.
ABER ich musste verwirrenden zusätzlichen Code schreiben, nur weil HTTP 404 zwei verschiedene Funktionen hatte:
- Wenn die Rest-API in der angegebenen URL nicht verfügbar ist, wird sie vom Anwendungsserver oder Webserver ausgelöst, auf dem die Rest-API-Anwendung ausgeführt wird
- Der Client erhält auch HTTP 404 zurück, wenn keine Daten in der Datenbank vorhanden sind, basierend auf der where-Bedingung der Abfrage.
Wichtig: Mein Rest-API-Fehlerbehandler fängt alle Ausnahmen ab, die im Back-End-Service angezeigt werden. Im Fehlerfall gibt meine Rest-API immer eine perfekte JSON-Nachricht mit den Nachrichtendetails zurück.
Dies ist die erste Version meiner Client-Hilfsmethode, die die zwei verschiedenen HTTP 404-Antworten verarbeitet:
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");
}
ABER , weil mein Java- oder JavaScript-Client irgendwie zwei Arten von HTTP 404 empfangen kann, muss ich im Fall von HTTP 404 den Text der Antwort überprüfen. Wenn ich den Antworttext analysieren kann, bin ich sicher, dass ich eine Antwort zurückbekommen habe, wo sie war Keine Daten zum Zurücksenden an den Client.
Wenn ich die Antwort nicht analysieren kann, bedeutet dies, dass ich vom Webserver (nicht von der restlichen API-Anwendung) ein echtes HTTP 404 zurückerhalten habe.
Es ist so verwirrend und die Client-Anwendung muss immer zusätzliche Analysen durchführen, um den wahren Grund von HTTP 404 zu überprüfen.
Ehrlich gesagt mag ich diese Lösung nicht. Es ist verwirrend und muss den Kunden ständig zusätzlichen Bullshit-Code hinzufügen.
Anstatt HTTP 404 in diesen beiden verschiedenen Szenarien zu verwenden, habe ich beschlossen, Folgendes zu tun:
- Ich verwende HTTP 404 nicht mehr als Antwort-HTTP-Code in meiner Restanwendung.
- Ich werde HTTP 204 (kein Inhalt) anstelle von HTTP 404 verwenden.
In diesem Fall kann der Clientcode eleganter sein:
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);
}
Ich denke, das behandelt dieses Problem besser.
Wenn Sie eine bessere Lösung haben, teilen Sie sie uns bitte mit.