How to return custom error codes in Cloud Endpoints?

As described here https://cloud.google.com/appengine/docs/java/endpoints/exceptions Google Cloud Endpoints only returns a very limited range of http status codes, namely:

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 suggests to use the existing status codes to return custom errors:

"In many situations, you may want to use common HTTP status codes to indicate the success or failure of a user's API request. For example, if a user is attempting to retrieve an entity which does not exist, you may want to send an HTTP 404 status code saying No entity exists with ID: entityId. You can send such common HTTP status codes by throwing an exception provided by the endpoints library as follows:

String message = "No entity exists with ID: " + entityId;
throw new NotFoundException(message);

"

Further down in the same document, Google states:

"Any other HTTP 4xx codes will be returned as error 404"

What's the problem with that? I throw 404 if my entity cannot be found, but Google also throws 404 for almost anything else that goes wrong.

With the exception of 401, 403, and 409, which I can use to tell my client what the exact error was (authorization, forbidden or conflict), I need to fall back to 400 and 404 for all my other status codes, with the result that my client never knows exactly what the problem was.

Sure I can include a human readable error message, but that is meant for RuntimeException(s) that occured in the server code, not to tell my client there was a problem with the data it sent.

Sure, I can also use the first few digits of the error description to send an application specific error code and send the generic 400 Bad Request, but I guess that's not how this should be done.

Any input appreciated. How do you return application specific error codes which your client can use to resolve an application-specific problem?


Having read the following and other posts

  • http://archive.oreilly.com/pub/post/restful_error_handling.html
  • Standard JSON API response format?
  • I would almost say what Google suggests is wrong, because there is no clear differentiation between http status codes and application codes. Both happen on different layers, and the client has no way to tell if it made a bad request, such as violating a contract (eg calling a non-existing endpoint, essentially a runtime error), or passing a wrong id (an application layer error).

    Articles suggest the following solutions:

  • use http error codes: not always possible as discussed above
  • add the application error as custom response header: I would not choose this because it won't appear in the log, which will make debugging tough.
  • always return 200 and wrap the result in a JSON (as sockets.io does): not viable with endpoints
  • I came up with another solution which I admit is a compromise (a violation of the error message, in fact), but which I believe is the best suitable integration of individual application error codes into Cloud Endpoints:

  • I extended 400 BadRequestException, so that any error message is returned as JSON. The client still receives receives http status code 400, but instead of a String error message, it receives a JSON string like this:
  • { "code": 400, "message": "This is a human readable error message." }

    And here I have two options: Either I return code 400, which means this is a BadRequestException where the client actually violated a contract, or I return any other application specific code, which the client can easily parse and process.

    My ApplicationException looks like this (it uses a custom JSONizer so it won't work for you like this but you could use JSONObject, GSON, Jackson, whatever):

    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());
        }
    
    }
    

    I haven't marked my answer as correct as I want you to keep posting further suggestions and comments if you believe there are better ways to do this.

    链接地址: http://www.djcxy.com/p/48068.html

    上一篇: 有没有被接受或出现的JSON格式和字段定义格式?

    下一篇: 如何在云终端中返回自定义错误代码?