Как описано здесь https://cloud.google.com/appengine/docs/java/endpoints/exceptions Google Cloud Endpoints возвращает только очень ограниченный диапазон кодов статуса http, а именно:
HTTP 400 BadRequestException
HTTP 401 UnauthorizedException
HTTP 403 ForbiddenException
HTTP 404 NotFoundException (also: Timeout)
HTTP 405
HTTP 408
HTTP 409 ConflictException
HTTP 410
HTTP 412
HTTP 413
Google предлагает использовать существующие коды статуса для возврата пользовательских ошибок:
"Во многих ситуациях вы можете использовать общие коды состояния HTTP, чтобы указывать на успех или неудачу запроса API-пользователя. Например, если пользователь пытается получить сущность, которая не существует, вы можете отправить HTTP-запрос 404, если не существует сущности с идентификатором: entityId. Вы можете отправить такие общие коды состояния HTTP, выбросив исключение, предоставляемое библиотекой конечных точек, следующим образом:
String message = "No entity exists with ID: " + entityId;
throw new NotFoundException(message);
"
Далее в том же документе Google заявляет:
"Любые другие коды HTTP 4xx будут возвращены как ошибка 404"
В чем проблема? Я бросаю 404, если моя сущность не может быть найдена, но Google также выбрасывает 404 для почти всего остального, что не так.
За исключением 401, 403 и 409, которые я могу использовать, чтобы сообщить моему клиенту, что такое точная ошибка (авторизация, запрет или конфликт), мне нужно вернуться к 400 и 404 для всех моих других кодов статуса, результат мой клиент никогда точно не знает, в чем проблема.
Конечно, я могу включить человекообразное сообщение об ошибке, но это предназначено для RuntimeException (ов), которое произошло в коде сервера, а не для того, чтобы сообщить моему клиенту, что проблема связана с переданными им данными.
Конечно, я также могу использовать первые несколько цифр описания ошибки, чтобы отправить код ошибки, специфичный для приложения, и отправить общий 400 Bad Request, но я думаю, что не так, как это должно быть сделано.
Любой вход оценивается. Как вы возвращаете специальные коды ошибок приложения, которые ваш клиент может использовать для решения конкретной проблемы?
Прочитав следующие и другие сообщения
Я бы почти сказал, что Google предлагает неправильно, потому что нет четкой дифференциации между кодами статуса http и кодами приложений. Оба варианта выполняются на разных уровнях, и клиент не может сказать, сделал ли он плохой запрос, например, нарушил контракт (например, вызвал несуществующую конечную точку, по существу, ошибку времени выполнения) или передал неправильный идентификатор (прикладной уровень ошибка).
В статьях предлагаются следующие решения:
Я придумал другое решение, которое, как я признаю, является компромиссом (на самом деле является нарушением сообщения об ошибке), но я считаю, что это лучшая подходящая интеграция отдельных кодов ошибок приложения в Cloud Endpoints:
{"code": 400, "message": "Это сообщение с возможностью чтения человеком". }
И здесь у меня есть два варианта: либо я возвращаю код 400, что означает, что это исключение BadRequestException, когда клиент фактически нарушил контракт, или я возвращаю любой другой код приложения, который клиент может легко разобрать и обработать.
My ApplicationException выглядит так (он использует пользовательский JSONizer, поэтому он не будет работать для вас так, но вы можете использовать JSONObject, GSON, Jackson, что угодно):
import com.google.api.server.spi.response.BadRequestException;
public class ApplicationException extends BadRequestException {
private static final int DEFAULT_APPLICATION_CODE = 400; // use this code for all requests without explicit code
public ApplicationException(int code, String message) {
super(JsonResponse.build()
.add("code", code)
.add("message", message)
.toString());
}
public ApplicationException(String message) {
super(JsonResponse.build()
.add("code", DEFAULT_APPLICATION_CODE)
.add("message", message)
.toString());
}
public ApplicationException(String message, Throwable cause) {
super(JsonResponse.build()
.add("code", DEFAULT_APPLICATION_CODE)
.add("message", message)
.toString());
}
}
Я не поставил свой ответ так правильно, что хочу, чтобы вы продолжали публиковать дальнейшие предложения и комментарии, если считаете, что есть лучшие способы сделать это.
400 This is a human readable error message.
вместо{ "code": 400, "message": "This is a human readable error message." }
- не очень хорошее решение, но, по крайней мере, анализируемое и четкое разделение ошибок сетевого уровня и приложений.