httpgohttphandlerchaining

Conditional Chaining of http handlers in golang


I want to conditionally add http handler based on certain condition

func ConditionalCheck(arg string) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            ctx := r.Context()
            check, ok := ctx.Value("specific").(bool);
            if check {
                SpecificCheck(arg)
            } else {
                next.ServeHTTP(w, r)
            }
        })
    }
}

func SpecificCheck(arg string) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // something
            next.ServeHTTP(w, r)
        })
    }
}

chain := alice.New(ConditionalCheck, .........)

When I test, the SpecificCheck HandlerFunc is not getting invoked. How do I chain this based on condition?


Solution

  • SepecificCheck just returns a function that takes one handler and returns another, it does not execute any of those returned objects. If you want to execute those objects you must do so explicitly, e.g.

    SepecificCheck(arg)(next).ServeHTTP(w, r)
    

    The above immediately calls the middleware function returned by SepecificCheck and then invokes the ServeHTTP method on the handler returned by that middleware function.

    Then the updated ConditionalCheck would like the following:

    func ConditionalCheck(arg string) func(http.Handler) http.Handler {
        return func(next http.Handler) http.Handler {
            return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                ctx := r.Context()
                check, ok := ctx.Value("specific").(bool)
                if check {
                    SpecificCheck(arg)(next).ServeHTTP(w, r)
                } else {
                    next.ServeHTTP(w, r)
                }
            })
        }
    }