Skip to content

Instantly share code, notes, and snippets.

@elithrar
Last active December 29, 2015 02:29
Show Gist options
  • Save elithrar/7600878 to your computer and use it in GitHub Desktop.
Save elithrar/7600878 to your computer and use it in GitHub Desktop.
use.go — the little HTTP middleware helper that could.
// use provides a cleaner interface for chaining middleware for single routes.
// Middleware functions are simple HTTP handlers (w http.ResponseWriter, r *http.Request)
//
// r.HandleFunc("/login", use(loginHandler, rateLimit, csrf))
// r.HandleFunc("/form", use(formHandler, csrf))
// r.HandleFunc("/about", aboutHandler)
func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
for _, m := range middleware {
h = m(h)
}
return h
}
// recuperate catches panics in handlers, logs the stack trace and and serves a HTTP 500 error.
//
// Example:
// http.Handle("/", recuperate(r))
func recuperate(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
http.Error(w, "HTTP 500: internal server error (we've logged it!)", http.StatusInternalServerError)
logger.Printf("Handler panicked: %s\n%s", err, debug.Stack())
}
}()
h.ServeHTTP(w, r)
})
}
@elithrar
Copy link
Author

This works:

r := mux.NewRouter()
r.HandleFunc("/form", use(formHandler, csrf)
http.Handle("/", r)

func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
    for _, m := range middleware {
        h = m(h)
    }

    return h
}

... where csrf is:

func csrf(h http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
                // do things
                h(w, r)
        }
}

and ... formHandler is:

func formHandler(w http.ResponseWriter, r *http.Request) {
      // do stuff
}

@elithrar
Copy link
Author

This does not work – update: see comment from kisielk

r := mux.NewRouter()
r.HandleFunc("/form", use(formHandler, csrf)
http.Handle("/", r)

func use(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
    for _, m := range middleware {
        h = m(h)
    }

    return h
}

... where csrf is:

func csrf(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // do stuff
        h.ServeHTTP(w, r)
    })
}

and ... formHandler is:

func formHandler(w http.ResponseWriter, r *http.Request) {
      // do stuff
}

@kisielk
Copy link

kisielk commented Nov 23, 2013

Try:

r := mux.NewRouter()
r.Handle("/form", use(http.HandlerFunc(formHandler), csrf))
http.Handle("/", r)

That should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment