Last active
August 6, 2019 10:13
-
-
Save jamesmccann/a8003a45f6daaa3dc84e04a78303f270 to your computer and use it in GitHub Desktop.
Go simple middleware chain, inspired by https://github.com/justinas/alice
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Middleware is a type alias for a function that | |
// accepts an http.Handler as the "next" handler in a chain | |
// and returns an http.Handler that will be executed before that handler. | |
type Middleware func(httprouter.Handle) httprouter.Handle | |
// MiddlewareChain represents a chain of middleware functions that can be | |
// assigned to wrap a handler function. | |
type MiddlewareChain []Middleware | |
// NewMiddlewareChain is a constructor for a chain of middlewares. | |
func NewMiddlewareChain(middlewares ...Middleware) MiddlewareChain { | |
return MiddlewareChain(append([]Middleware{}, middlewares...)) | |
} | |
// Wrap the final http.Handler with a closure which invokes all | |
// chained middlewares in the order they were constructed. | |
// E.g. for New(m1, m2, m3) we get m1(m2(m3(h))) which produces | |
// an execution chain of m1 -> m2 -> m3 -> h for each request. | |
func (mw MiddlewareChain) Wrap(h httprouter.Handle) httprouter.Handle { | |
if len(mw) == 0 { | |
return h | |
} | |
if h == nil { | |
// no-op handler | |
h = func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | |
http.DefaultServeMux.ServeHTTP(w, r) | |
} | |
} | |
// chain all the handlers together in the order they were called | |
// i.e. for NewMiddlewareChain(mw1, mw2, mw3) we get h = mw1 -> mw2 -> mw3 -> h | |
for i := range mw { | |
h = mw[len(mw)-1-i](h) // set h to "next" backwards through the chain | |
} | |
return h | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Middleware is a type alias for a function that | |
// accepts an http.Handler as the "next" handler in a chain | |
// and returns an http.Handler that will be executed before that handler. | |
type Middleware func(http.Handler) http.Handler | |
// MiddlewareChain represents a chain of middleware functions that can be | |
// assigned to wrap a handler function. | |
type MiddlewareChain []Middleware | |
// NewMiddlewareChain is a constructor for a chain of middlewares. | |
func NewMiddlewareChain(middlewares ...Middleware) MiddlewareChain { | |
return MiddlewareChain(append([]Middleware{}, middlewares...)) | |
} | |
// Wrap the final http.Handler with a closure which invokes all | |
// chained middlewares in the order they were constructed. | |
// E.g. for New(m1, m2, m3) we get m1(m2(m3(h))) which produces | |
// an execution chain of m1 -> m2 -> m3 -> h for each request. | |
func (mw MiddlewareChain) Wrap(h http.Handler) http.Handler { | |
if len(mw) == 0 { | |
return h | |
} | |
if h == nil { | |
h = http.DefaultServeMux | |
} | |
// chain all the handlers together in the order they were called | |
// i.e. for NewMiddlewareChain(mw1, mw2, mw3) we get h = mw1 -> mw2 -> mw3 -> h | |
for i := range mw { | |
h = mw[len(mw)-1-i](h) // set h to "next" backwards through the chain | |
} | |
return h | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment