How to do error http error handling in Go language

24,446

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)
    }
}
Share:
24,446
Jagrati
Author by

Jagrati

By Day : Work and Code on different applications such as ReactJS, Golang, HTML....... For Fun : Photo Editing, Singing Moto : Fake it Till You make it

Updated on September 30, 2020

Comments

  • Jagrati
    Jagrati over 3 years

    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
        }