Created
September 11, 2017 08:14
-
-
Save gbbr/85448fc35bf1a008363a4f5da469fa4d to your computer and use it in GitHub Desktop.
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
package main | |
import ( | |
"fmt" | |
"log" | |
"net/http" | |
) | |
func init() { | |
log.SetFlags(log.Lshortfile) | |
} | |
// middleware provides a convenient mechanism for filtering HTTP requests | |
// entering the application. It returns a new handler which performs various | |
// operations and finishes with calling the next HTTP handler. | |
type middleware func(http.HandlerFunc) http.HandlerFunc | |
// chainMiddleware provides syntactic sugar to create a new middleware | |
// which will be the result of chaining the ones received as parameters. | |
func chainMiddleware(mw ...middleware) middleware { | |
return func(final http.HandlerFunc) http.HandlerFunc { | |
return func(w http.ResponseWriter, r *http.Request) { | |
last := final | |
for i := len(mw) - 1; i >= 0; i-- { | |
last = mw[i](last) | |
} | |
last(w, r) | |
} | |
} | |
} | |
func withLogging(next http.HandlerFunc) http.HandlerFunc { | |
return func(w http.ResponseWriter, r *http.Request) { | |
log.Printf("Logged connection from %s", r.RemoteAddr) | |
next.ServeHTTP(w, r) | |
} | |
} | |
func withTracing(next http.HandlerFunc) http.HandlerFunc { | |
return func(w http.ResponseWriter, r *http.Request) { | |
log.Printf("Tracing request for %s", r.RequestURI) | |
next.ServeHTTP(w, r) | |
} | |
} | |
func home(w http.ResponseWriter, r *http.Request) { | |
log.Println("reached home") | |
fmt.Fprintf(w, "welcome") | |
} | |
func main() { | |
mw := chainMiddleware(withLogging, withTracing) | |
http.Handle("/", mw(home)) | |
log.Fatal(http.ListenAndServe(":8080", nil)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@gbbr thanks for smallest middleware chaining example.
One minor feedback, in
chainMiddleware
, for each new request, the for_loop will get executed. We can avoid this by taking for_loop just one level up (outer func) so that on every new request this loop will not run. This for_loop run once when new handler is registered. Every time new request arrives, it just calllast
and the magic of middleware chaining will happen. Here is modified version link