Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do error http error handling in Go language

I am little confused on how error handling should be done in go. I have read so many posts about it but still am not able to apply them on my structure of code. I am new to go so please help.

There is a main function which handles two apis: api1 and api2

func main() {
    http.HandleFunc("/offers", api1)
    http.HandleFunc("/getOffersList", api2)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}


func api1(w http.ResponseWriter, req *http.Request) {
    validateRequestHeader(w, req, "GET")
    // code here....
}

func api2(w http.ResponseWriter, req *http.Request) {
    validateRequestHeader(w, req, "POST")
    //code here....
}

func validateRequestHeader(w http.ResponseWriter, req *http.Request, allowedMethod string) {
    // allow cross domain AJAX requests
    w.Header().Set("Content-Type", "application/json")
    if origin := req.Header.Get("Origin"); origin != "" {
        w.Header().Set("Access-Control-Allow-Origin", origin)
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers",
            "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    }
    // Stop here if its Preflighted OPTIONS request
    if req.Method == "OPTIONS" {
        return
    }
    if req.Method != allowedMethod {
        response := "Only " + allowedMethod + " requests are allowed"
        http.Error(w, response, http.StatusMethodNotAllowed)
        return
    }
}

In both api1 and api2 , function validateRequestHeader is getting called. If this gets true, then in the api1/api2 further code is getting executed which I do not want. How it should be handled?

if req.Method != allowedMethod {
        response := "Only " + allowedMethod + " requests are allowed"
        http.Error(w, response, http.StatusMethodNotAllowed)
        return
    }
like image 283
Jagrati Avatar asked May 05 '17 08:05

Jagrati


People also ask

How do I make errors in Golang?

Creating custom errors using the New function The implementation is pretty simple. errorString is a struct type with a single string field s . The Error() string method of the error interface is implemented using a errorString pointer receiver in line no. 14.

How should you log an error err in Go?

Errors can be returned as nil , and in fact, it's the default, or “zero”, value of on error in Go. This is important since checking if err != nil is the idiomatic way to determine if an error was encountered (replacing the try / catch statements you may be familiar with in other programming languages).

What is HTTP error handling?

Automatically handles uncaught errors that contain the properties statusCode (number) and message (string) and creates a proper HTTP response for them (using the message and the status code provided by the error object).


1 Answers

This blog post goes into some details on how to chain multiple handler functions, which is what you should be doing. That way, you can have a validation handler, a logging handler, an authorization handler, etc etc. and just chain them together.

Essentially

func validator(next http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, req *http.Request) {
            if isRequestValid(req) {
                // a valid request is passed on to next handler
                next.ServeHTTP(w, req)
            } else {
                // otherwise, respond with an error
                http.Error(w, "Bad request - Go away!", 400)
            }
    }
    return http.HandlerFunc(fn)
}

func api1() http.Handler {
    fn := func(w http.ResponseWriter, req *http.Request) {
            // api 1 code
    }
    return http.HandlerFunc(fn)
}

func api2() http.Handler {
    fn := func(w http.ResponseWriter, req *http.Request) {
            // api 2 code
    }
    return http.HandlerFunc(fn)
}

And then chain them up in your main function.

func main() {
    http.Handler("/offers", validate(api1()))
    http.Handler("/getOffersList", validate(api2()))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
like image 103
Emil H Avatar answered Oct 09 '22 00:10

Emil H