Esa es una publicación muy antigua pero me enfrenté a un problema similar y me gustaría compartir mi experiencia con ustedes.
Estoy construyendo una arquitectura de microservicios con API de descanso. Tengo algunos servicios GET de descanso, recopilan datos del sistema de fondo en función de los parámetros de solicitud.
Seguí el resto de los documentos de diseño de la API y envié HTTP 404 con un mensaje de error JSON perfecto al cliente cuando no había datos que se alinearan con las condiciones de la consulta (por ejemplo, se seleccionó el registro cero).
Cuando no había datos para enviar de vuelta al cliente, preparé un mensaje JSON perfecto con código de error interno, etc. para informar al cliente sobre el motivo de "No encontrado" y se lo devolvió al cliente con HTTP 404. Eso funciona bien.
Más tarde, he creado una clase de cliente API de descanso que es un ayudante fácil para ocultar el código relacionado con la comunicación HTTP y usé este ayudante todo el tiempo cuando llamé a mis API de descanso desde mi código.
PERO necesitaba escribir código extra confuso solo porque HTTP 404 tenía dos funciones diferentes:
- el HTTP 404 real cuando el resto API no está disponible en la URL dada, es arrojado por el servidor de aplicaciones o el servidor web donde se ejecuta el resto de la aplicación API
- el cliente también recupera HTTP 404 cuando no hay datos en la base de datos en función de la condición where de la consulta.
Importante: mi controlador de errores de la API de rest detecta todas las excepciones que aparecen en el servicio de back-end, lo que significa que, en caso de error, mi API de rest siempre regresa con un mensaje JSON perfecto con los detalles del mensaje.
Esta es la primera versión del método auxiliar de mi cliente que maneja las dos respuestas 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");
}
PERO , debido a que mi cliente Java o JavaScript puede recibir dos tipos de HTTP 404 de alguna manera, necesito verificar el cuerpo de la respuesta en el caso de HTTP 404. Si puedo analizar el cuerpo de la respuesta, entonces estoy seguro de que recibí una respuesta donde había No hay datos para enviar al cliente.
Si no puedo analizar la respuesta, eso significa que recuperé un HTTP 404 real del servidor web (no de la aplicación API del resto).
Es muy confuso y la aplicación cliente siempre necesita realizar un análisis adicional para verificar la razón real de HTTP 404.
Sinceramente, no me gusta esta solución. Es confuso, necesita agregar código extra de mierda a los clientes todo el tiempo.
Entonces, en lugar de usar HTTP 404 en estos dos escenarios diferentes, decidí que haré lo siguiente:
- Ya no estoy usando HTTP 404 como código HTTP de respuesta en mi aplicación de descanso.
- Voy a usar HTTP 204 (Sin contenido) en lugar de HTTP 404.
En ese caso, el código del cliente puede ser más 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);
}
Creo que esto maneja ese problema mejor.
Si tiene alguna solución mejor, compártala con nosotros.