Questo è un post molto vecchio, ma ho dovuto affrontare un problema simile e vorrei condividere la mia esperienza con voi ragazzi.
Sto costruendo un'architettura microservice con API di riposo. Ho alcuni servizi GET di riposo, raccolgono dati dal sistema di back-end in base ai parametri della richiesta.
Ho seguito i restanti documenti di progettazione dell'API e ho inviato HTTP 404 con un perfetto messaggio di errore JSON al client quando non c'erano dati allineati alle condizioni della query (ad esempio è stato selezionato il record zero).
Quando non c'erano dati da rispedire al client, ho preparato un messaggio JSON perfetto con codice di errore interno, ecc. Per informare il cliente sul motivo del "Non trovato" ed è stato rispedito al client con HTTP 404. Che funziona bene.
Più tardi ho creato una classe client API di riposo che è un aiuto semplice per nascondere il codice relativo alla comunicazione HTTP e ho usato questo aiuto tutto il tempo quando ho chiamato le mie API di riposo dal mio codice.
MA avevo bisogno di scrivere codice extra confuso solo perché HTTP 404 aveva due diverse funzioni:
- il vero HTTP 404 quando l'API di riposo non è disponibile nell'URL specificato, viene generata dal server delle applicazioni o dal server Web in cui è in esecuzione l'applicazione dell'API di riposo
- il client recupera anche HTTP 404 quando non ci sono dati nel database in base alla condizione in cui la query.
Importante: il gestore degli errori dell'API di riposo rileva tutte le eccezioni visualizzate nel servizio back-end, il che significa che in caso di errore l'API di riposo restituisce sempre con un messaggio JSON perfetto con i dettagli del messaggio.
Questa è la prima versione del mio metodo di supporto client che gestisce le due diverse risposte 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");
}
MA , poiché il mio client Java o JavaScript può ricevere due tipi di HTTP 404 in qualche modo ho bisogno di controllare il corpo della risposta in caso di HTTP 404. Se riesco ad analizzare il corpo della risposta, sono sicuro di aver ricevuto una risposta dove c'era nessun dato da rispedire al client.
Se non riesco ad analizzare la risposta, ciò significa che ho recuperato un HTTP 404 reale dal server Web (non dall'applicazione API restante).
È così confuso e l'applicazione client deve sempre eseguire analisi aggiuntive per verificare il vero motivo di HTTP 404.
Onestamente non mi piace questa soluzione. È fonte di confusione, deve aggiungere continuamente codice di cazzate ai clienti.
Quindi, invece di utilizzare HTTP 404 in questi due diversi scenari, ho deciso di fare quanto segue:
- Non sto più usando HTTP 404 come codice HTTP di risposta nella mia applicazione di riposo.
- Userò HTTP 204 (nessun contenuto) invece di HTTP 404.
In tal caso il codice client può essere più elegante:
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);
}
Penso che questo gestisca meglio questo problema.
Se hai una soluzione migliore, condividila con noi.