Esse é um post muito antigo, mas enfrentei um problema semelhante e gostaria de compartilhar minha experiência com vocês.
Estou construindo uma arquitetura de microsserviço com APIs restantes. Eu tenho alguns serviços GET em repouso, eles coletam dados do sistema back-end com base nos parâmetros de solicitação.
Segui os demais documentos de design da API e enviei HTTP 404 com uma mensagem de erro JSON perfeita para o cliente quando não havia dados alinhados às condições da consulta (por exemplo, zero registro foi selecionado).
Quando não havia dados a serem devolvidos ao cliente, preparei uma mensagem JSON perfeita com código de erro interno etc. para informar o cliente sobre o motivo do "Não encontrado" e ele foi enviado de volta ao cliente com HTTP 404. Isso funciona bem.
Posteriormente, criei uma classe de cliente da API Rest, que é um auxiliar fácil para ocultar o código relacionado à comunicação HTTP e usei esse auxiliar o tempo todo quando chamei minhas APIs de descanso do meu código.
MAS eu precisava escrever um código extra confuso apenas porque o HTTP 404 tinha duas funções diferentes:
- o HTTP 404 real quando a API restante não está disponível no URL fornecido, é lançada pelo servidor de aplicativos ou servidor da web em que o aplicativo API restante é executado
- o cliente recebe HTTP 404 também quando não há dados no banco de dados com base na condição where da consulta.
Importante: Meu manipulador de erros da API de descanso captura todas as exceções que aparecem no serviço de back-end, o que significa que, em caso de erro, minha API de descanso sempre retorna com uma mensagem JSON perfeita com os detalhes da mensagem.
Esta é a primeira versão do meu método auxiliar de cliente que lida com as duas respostas HTTP 404 diferentes:
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");
}
MAS , porque meu cliente Java ou JavaScript pode receber dois tipos de HTTP 404 de alguma forma, preciso verificar o corpo da resposta no caso do HTTP 404. Se eu puder analisar o corpo da resposta, tenho certeza de que recebi de volta uma resposta onde havia sem dados para enviar de volta ao cliente.
Se não conseguir analisar a resposta, significa que recebi um HTTP 404 real do servidor da Web (não do aplicativo API restante).
É tão confuso e o aplicativo cliente sempre precisa fazer uma análise extra para verificar o real motivo do HTTP 404.
Honestamente, eu não gosto desta solução. É confuso, precisa adicionar código extra de besteira aos clientes o tempo todo.
Portanto, em vez de usar o HTTP 404 nesses dois cenários diferentes, decidi que faria o seguinte:
- Não estou mais usando HTTP 404 como código HTTP de resposta no meu aplicativo de descanso.
- Vou usar o HTTP 204 (sem conteúdo) em vez do HTTP 404.
Nesse caso, o código do cliente pode ser mais 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);
}
Eu acho que isso lida melhor com esse problema.
Se você tiver alguma solução melhor, compartilhe-a conosco.