Reputation: 950
Is there an easy way to set a callback function that is called on every HTTP request made to a gorilla/mux HTTP webserver? They don't seem to have a notion of setting a callback function in their docs.
I wanted to check one of the headers for some information on every call to my server.
Upvotes: 0
Views: 1140
Reputation: 33370
If you want to have a handler that can receive all requests in the router you can use alice to chain your handlers together.
This is a simple way to act on all incoming requests.
Here is an example:
package main
import (
"net/http"
"github.com/gorilla/mux"
"github.com/justinas/alice"
)
func MyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if len(r.URL.Path) > 1 {
http.Error(w, "please only call index because this is a lame example", http.StatusNotFound)
return
}
next.ServeHTTP(w, r)
})
}
func Handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello"))
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/", Handler)
r.HandleFunc("/fail", Handler)
chain := alice.New(MyMiddleware).Then(r)
http.ListenAndServe(":8080", chain)
}
Upvotes: 2
Reputation: 40759
gorilla/mux itself is just a router and dispatcher, which, although technically could do what you're asking, is not really what it's designed for.
The "idiomatic" approach is to wrap your handler with middleware that decorates your handler with any additional functions, like one to check headers for some information on every call.
Expanding on the gorilla/mux full example, you could do something like:
package main
import (
"log"
"net/http"
"github.com/gorilla/mux"
)
func HeaderCheckWrapper(requiredHeader string, original func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if foo, ok := r.Header[requiredHeader]; ok {
// do whatever with the header value, and then call the original:
log.Printf("Found header %q, with value %q", requiredHeader, foo)
original(w, r)
return
}
// otherwise reject the request
w.WriteHeader(http.StatusPreconditionFailed)
w.Write([]byte("missing expected header " + requiredHeader))
}
}
func YourHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Gorilla!\n"))
}
func main() {
r := mux.NewRouter()
// Routes consist of a path and a handler function.
r.HandleFunc("/", HeaderCheckWrapper("X-Foo-Header", YourHandler))
// Bind to a port and pass our router in
log.Fatal(http.ListenAndServe(":8000", r))
}
Upvotes: 2