2
votes

I'm coming from node express, and I was able to pass in as many middleware as possible, for example: routes.use('/*', ensureAuth, logImportant, ... n);

How can I do something similar when using r.GET("/", HomeIndex)?

Am I forced to do something like EnsureAuth(HomeIndex)? Because I can get that to work. Unfortunately, I'm not sure what would be a good way to add as many middlewares as I want without chaining functions together.

Is there a more elegant way so I could somehow use variadic type function to do r.GET("/", applyMiddleware(HomeIndex, m1, m2, m3, m4)? I'm trying that out right now, but I feel like there's a better way to do this.

I've looked at the httprouter issues page, can't find anything :(

Thanks!

1
just a question, do you strictly need httprouter?stevenferrer
i'm new to Go and I read some articles and read that for JSON api httprouter would be fast performance and easy to use.a person
how about your middlewares, are they of this signature func(http.Handler) http.Handler?stevenferrer
yes. Well, I'm returning httprouter.Handle, and passing in handle of type httprouter.Handle.a person
see if this package could help you github.com/justinas/alicestevenferrer

1 Answers

3
votes

Here is an example how I did it:

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"

    "github.com/julienschmidt/httprouter"
    "github.com/justinas/alice"
)

// m1 is middleware 1
func m1(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //do something with m1
        log.Println("m1 start here")
        next.ServeHTTP(w, r)
        log.Println("m1 end here")
    })
}

// m2 is middleware 2
func m2(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //do something with m2
        log.Println("m2 start here")
        next.ServeHTTP(w, r)
        log.Println("m2 end here")
    })
}

func index(w http.ResponseWriter, r *http.Request) {
    // get httprouter.Params from request context
    ps := r.Context().Value("params").(httprouter.Params)
    fmt.Fprintf(w, "Hello, %s", ps.ByName("name"))
}

// wrapper wraps http.Handler and returns httprouter.Handle
func wrapper(next http.Handler) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        //pass httprouter.Params to request context
        ctx := context.WithValue(r.Context(), "params", ps)
        //call next middleware with new context
        next.ServeHTTP(w, r.WithContext(ctx))
    }
}

func main() {
    router := httprouter.New()

    chain := alice.New(m1, m2)

    //need to wrap http.Handler to be compatible with httprouter.Handle
    router.GET("/user/:name", wrapper(chain.ThenFunc(index)))

    log.Fatal(http.ListenAndServe(":9000", router))
}

Link to code (you can't run it from play.golang.org though): https://play.golang.org/p/BOCt97xcoY