Это очень старый пост, но я столкнулся с подобной проблемой, и я хотел бы поделиться своим опытом с вами, ребята.
Я строю микросервисную архитектуру с остальными API. У меня есть некоторые остальные сервисы GET, они собирают данные из серверной системы на основе параметров запроса.
Я следовал за остальными документами разработки API и отправлял обратно HTTP 404 с совершенным сообщением об ошибке JSON клиенту, когда не было данных, соответствующих условиям запроса (например, была выбрана нулевая запись).
Когда не было данных для отправки обратно клиенту, я подготовил идеальное сообщение JSON с внутренним кодом ошибки и т. Д., Чтобы проинформировать клиента о причине «Не найдено», и оно было отправлено обратно клиенту с HTTP 404. работает отлично.
Позже я создал клиентский класс rest API, который является простым помощником для скрытия кода, связанного с HTTP-связью, и я использовал этот помощник все время, когда вызывал свои API отдыха из своего кода.
НО мне нужно было написать непонятный дополнительный код только потому, что HTTP 404 имел две разные функции:
- реальный HTTP 404, когда остальной API недоступен в данном URL-адресе, он генерируется сервером приложений или веб-сервером, на котором выполняется остальное API-приложение
- клиент возвращает HTTP 404 также, когда в базе данных нет данных, основанных на условии, где запрос.
Важное замечание: мой обработчик ошибок API rest перехватывает все исключения, появляющиеся в серверной службе, что означает, что в случае любой ошибки мой API rest всегда возвращает идеальное сообщение JSON с деталями сообщения.
Это первая версия моего вспомогательного метода клиента, который обрабатывает два разных ответа 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");
}
НО , поскольку мой клиент Java или JavaScript может каким-то образом получать два вида HTTP 404, мне нужно проверить тело ответа в случае HTTP 404. Если я могу проанализировать тело ответа, то я уверен, что получил ответ там, где был нет данных для отправки обратно клиенту.
Если я не могу разобрать ответ, это означает, что я получил реальный HTTP 404 с веб-сервера (а не из остального приложения API).
Это настолько сбивает с толку, и клиентское приложение всегда должно делать дополнительный анализ, чтобы проверить истинную причину HTTP 404.
Честно говоря, мне не нравится это решение. Это сбивает с толку, необходимо постоянно добавлять дополнительный дерьмовый код клиентам.
Поэтому вместо использования HTTP 404 в этих двух разных сценариях я решил, что сделаю следующее:
- Я больше не использую HTTP 404 в качестве ответного HTTP-кода в моем приложении для отдыха.
- Я собираюсь использовать HTTP 204 (без содержимого) вместо HTTP 404.
В этом случае клиентский код может быть более элегантным:
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);
}
Я думаю, что это решает эту проблему лучше.
Если у вас есть лучшее решение, поделитесь им с нами.