Description
Hello there,
I've been using gorilla/mux
for a while on an internal project at my organization, and due to some requirements, I ended up forking the project and adding some extra features, such as internal support for middleware.
Yes, I am aware that negroni is a thing, and that it also provides this functionality. However, there are a few key things you can't do just chaining mux
after your middleware:
-
Acting only if a route match is found: Waiting to see if a route actually matches before acting allows for more flexibility and coherent design. For example, an authentication middleware can happily return 403 if the required credentials are not supplied, and at the same time a normal 404 will be returned by
mux
if the route does not exist. This option does not exist if you need to process authentication headers before the request is matched. -
Adding middleware for subrouters is simpler if it is embed inside
mux
. -
It is more efficient. If your site receives heavy traffic and your middleware performs heavy tasks, you'll appreciate this kind of saving.
After pondering a bit, I decided that this simple addon was worth implementing, so I did.
As a middleware needs to be able to stop the handlers chain, I implemented it using a slightly modified http.Handler
interface:
type Middleware interface {
ServeHTTP(http.ResponseWriter, *http.Request) (http.ResponseWriter, *http.Request)
}
type MiddlewareFunc func(http.ResponseWriter, *http.Request) (http.ResponseWriter, *http.Request)
If the middleware implementations return nil as either http.ResponseWriter
or *http.Request
the chain is stopped. Also, http.ResponseWriter
and *http.Request
can be hijacked if the middleware wants to. This is an approach slightly different to negroni's, where a third parameter of *http.HandlerFunc
is added. I thought this way were better as it simplifies greatly building and iterating the middleware chain. Also, I don't like recursion. Of course, wrapper functions which receive http.Handler
and http.HandlerFunc
exists, so standard handlers can be chained too.
I'm not sure if you think this feature is kind of out-of scope. But if you don't, I'll happily open a PR and discuss any modifications or style changes you'd want to be done.
Activity