Unified custom error handling for ECHO frames

Source: Internet
Author: User
Tags key string
This is a creation in Article, where the information may have evolved or changed.

With the growth of the mobile side, today's RESTful API is already popular,
In various languages to write back-end API has a very mature and convenient solution, with Golang write back-end API is a representative of productivity,
You can write back-end APIs that perform up to one or two orders of magnitude without losing the speed of a dynamic language such as Python/ruby.

ECHO Frame

Because the Golang standard library is already very perfect in the network aspect, causes the frame to play the room to be not big. Many experts say,
With what frame, with the standard library is written, the framework is only the grammatical sugar, but also restricts the development of the project.
But we are not a master, grammar sugar is also sugar, with a hand in the frame or can improve a lot of efficiency.
If in six months ago, you let me recommend the framework, I would say there are many, all have advantages and disadvantages, in addition to Beego casually choose one can.
But in the 2017, a Echo frame called the fore. This is my most recommended framework at the moment.
Echo's advocacy pragmatic is "high-performance, easy to expand, minimalist Go Web framework." Some of its features are as follows:

In these features, Http/2,auto HTTPS, listening very well? This is the feature that I introduced before Caddy,
Because Golang implementation of these is too easy. There are also a lot of functions in the middleware.
When we do microservices, these generic things are implemented by the API Gateway,
If you're writing a small, standalone app backend, these out-of-the-box features can be a great help.

In fact, today I would like to talk about the last feature mentioned, "Centralized HTTP error handling."

RESTful API Error returned

A team should have a specification for the RESTful API, and the response format should be normalized in the specification, including the format of all error responses.
Like Microsoft's specs,
Jsonapi.org recommended specifications and so on.
Most of the time we don't need to implement the tedious, we specify a simple structure:

STATUS 400 Bad Request{  "error": "InvalidID",  "message": "invalid id in your url query parameters"}

The traditional error response may have only a string type of message that accompanies the HTTP Status code,
Now that we've turned the normal response format into JSON, we'll use JSON to return the error.
In addition to using JSON, we have added an error field,
This field is a level Key that is more detailed than the Status code,
The consumer can use this convention Key to do more flexible error handling.

Well, let's go on with this simple example, and today's topic is about Echo's approach to unified processing.

How does Echo handle errors uniformly?

In fact, the Echo of the document although very beautiful, but not enough detail, in-depth a bit of content and examples are not.
But a nice Golang project, the code is documentation, we should have the habit of going to godoc.org to check the documentation.
We found Echo's Godoc,
Look at the Echo type:

type Echo struct {    Server           *http.Server    TLSServer        *http.Server    Listener         net.Listener    TLSListener      net.Listener    DisableHTTP2     bool    Debug            bool    HTTPErrorHandler HTTPErrorHandler    Binder           Binder    Validator        Validator    Renderer         Renderer    AutoTLSManager   autocert.Manager    Mutex            sync.RWMutex    Logger           Logger    // contains filtered or unexported fields}

Sure enough, you can define Httperrorhandler, follow through,

// HTTPErrorHandler is a centralized HTTP error handler.type HTTPErrorHandler func(error, Context)

It is a function that passes in the error and Context and has no return value.
But you know this is a little dizzy? Do not know how to write this function ah.
It's okay, this article is about how to write this function. Look down.

Defining the error structure

Since Golang is a static type, we need to define a structure first, the code is as follows:

type httpError struct {    code    int    Key     string `json:"error"`    Message string `json:"message"`}func newHTTPError(code int, key string, msg string) *httpError {    return &httpError{        code:    code,        Key:     key,        Message: msg,    }}// Error makes it compatible with `error` interface.func (e *httpError) Error() string {    return e.Key + ": " + e.Message}

We've done three things here.

    1. Defines the structure of the error, which contains Code,key and Message,key and the message can be exported as JSON.

    2. Make a new error structure function, so you can use a line of code to create a new error.

    3. Adds a function to the structure so that the Error structure becomes a Golang error interface.

Handling Errors

We can finally write the custom function mentioned above, first look at the sample code I'll explain, and then you can write your own:

 package mainimport ("Net/http" "Github.com/labstack/echo")//Httperrorhandler Customize E Cho ' s HTTP error handler.func Httperrorhandler (err error, C echo. Context) {var (code = HTTP). Statusinternalservererror key = "Servererror" msg string) if he, OK: = Err. (*httperror); OK {code = He.code key = He. Key msg = He. Message} else if config. Debug {msg = err. Error ()} else {msg = http. StatusText (Code)} if!c.response (). Committed {if C.request (). Method = = echo. HEAD {err: = c.nocontent (code) if err! = Nil {C.logger (). Error (ERR)}} else {err: = C.json (Code, NEWHTTPERROR (Code, key, MSG)) If err! = Nil {C.logger (). Error (Err)}}}}  

The function is to assemble the appropriate HTTP response based on the error and context in which it is passed.
But because the Golang error is an interface, that is, the first parameter may come in any strange things,
We need to deal with it carefully.

In the first part we define the default values as the worst case scenario, and in the HTTP API, the consumer sees this worst case scenario,
Note that you are going to be deducted from the bonus unless you can throw a pot to your dependent module or infrastructure.

In the second part, we first look at the errors that we have defined before, and if so, it would be great. If not,
It seems to be an other unknown error, if the Debug is open, it is OK, no deduction bonus, we put the error details directly back
Easy to debug in Msg. If you do not open Debug ... That had to bite the bullet back to 500 and what information is not given.

The third part you can basically copy, is to check whether the context of the declaration that the response has been submitted, only when not submitted,
We just need to put our prepared error message in JSON format, and print the error log by the way. In addition, if the request
Is the HEAD method, according to the specification, you can only return status 204 and silently in the log record error.

Application

Well, we have written a unified error handling, how to use it? Let's look at a minimalist example:

func getUser(c echo.Context) error {    var u user    id := c.Param("id")    if !bson.IsObjectIdHex(id) {        return newHTTPError(http.StatusBadRequest, "InvalidID", "invalid user id")    }    err := db.C("user").FindId(bson.ObjectIdHex(id)).One(&u)    if err == mgo.ErrNotFound {        return newHTTPError(http.StatusNotFound, "NotFound", err.Error())    }    if err != nil {        return err    }    return c.JSON(http.StatusOK, u)}

This is an example of taking the user from MongoDB,

    1. Check that the ID in the URL is not a valid ID, or return our previous custom error.

    2. Go to the database and return a 404 error if there is no record.

    3. If there are other errors in querying the database, there is nothing we can do about it, so we have to return the error directly.

    4. If everything is OK, we return the status 200 and JSON data.

We can see, after such a toss, in the writing API, the worry a lot.
We can use a line of code to construct the error, or you can directly return any errors that are not predicted,
No more trouble to construct 500 errors at a time.

What do you think? It's really convenient to go to the Amway partners and write the HTTP API with Echo.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.