Search code examples
httpgomiddleware

How can I terminate my handler early if some permission check fails?


I am finding a way to implement the permission check functionality using http

The idea is there are APIs that should be used only by login sessions.

func CheckPermissionFilter(w http.ResponseWriter, r *http.Response){
    sid, err := r.Cookie("sid")
    // check the permission with sid, if permission is granted then just let the 
    // process go on, otherwise, just break the filter chain and return Http Error Code.

}

func SomeHttpHandler(w http.ResponseWriter, r *http.Response){
     CheckPermissionFilter(w, r)
     // if not breaked by above filter function, process the request...
   
}

I have no problem with the permission checking, but I can't find a way to break the HTTP Request processing.


Solution

  • The call to CheckPermissionFilter within your SomeHttpHandler handler cannot terminate the latter early. Instead, you should define CheckPermissionFilter as a middleware (see also decorator pattern):

    package main
    
    import (
        "net/http"
    )
    
    func main() {
        http.Handle("/foo", CheckPermissionFilter(SomeHttpHandler))
        // ...
    }
    
    func CheckPermissionFilter(h http.HandlerFunc) http.HandlerFunc {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            sid, err := r.Cookie("sid")
            // handle err
            if !Validate(sid) {
                http.Error(w, "Unauthorized", http.StatusUnauthorized)
                return
            }
            h(w, r)
        })
    }
    
    func SomeHttpHandler(w http.ResponseWriter, r *http.Request) {
        // ...
    }
    
    func Validate(sid string) bool {
        return true // simplistic implementation for this example
    }