Last active
August 20, 2019 10:19
-
-
Save rogerwelin/4c664fca4ec1bc3144fccd0d1f159b80 to your computer and use it in GitHub Desktop.
Http middlewares in Go
This file contains hidden or 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" | |
| "time" | |
| "github.com/gorilla/mux" | |
| ) | |
| // MiddlewareInterceptor intercepts an HTTP handler invocation | |
| type MiddlewareInterceptor func(http.ResponseWriter, *http.Request, http.HandlerFunc) | |
| // MiddlewareHandlerFunc builds on top of http.HandlerFunc, and exposes API to intercept with MiddlewareInterceptor | |
| type MiddlewareHandlerFunc http.HandlerFunc | |
| // MiddlewareChain is a slice of interceptors that will be invoked in their index order | |
| type MiddlewareChain []MiddlewareInterceptor | |
| // Intercept returns back a continuation that will call install middleware to intercept the continuation call | |
| func (cont MiddlewareHandlerFunc) Intercept(mw MiddlewareInterceptor) MiddlewareHandlerFunc { | |
| return func(writer http.ResponseWriter, request *http.Request) { | |
| mw(writer, request, http.HandlerFunc(cont)) | |
| } | |
| } | |
| // Handler allows hooking multiple middleware in single call | |
| func (chain MiddlewareChain) Handler(handler http.HandlerFunc) http.Handler { | |
| current := MiddlewareHandlerFunc(handler) | |
| for i := len(chain) - 1; i >= 0; i-- { | |
| mv := chain[i] | |
| current = current.Intercept(mv) | |
| } | |
| return http.HandlerFunc(current) | |
| } | |
| func NewReqIDInterceptor() MiddlewareInterceptor { | |
| return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { | |
| if r.Header.Get("X-Request-Id") == "" { | |
| r.Header.Set("X-Request-Id", "123abc") | |
| log.Println(r.Header) | |
| } | |
| next(w, r) | |
| } | |
| } | |
| func ElapsedTimeInterceptor() MiddlewareInterceptor { | |
| return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { | |
| startTime := time.Now() | |
| defer func() { | |
| endTime := time.Now() | |
| elapsedTime := endTime.Sub(startTime) | |
| log.Println("Elapsed time:", elapsedTime) | |
| }() | |
| next(w, r) | |
| } | |
| } | |
| func indexHandler(w http.ResponseWriter, r *http.Request) { | |
| fmt.Fprintf(w, "some work here") | |
| } | |
| func main() { | |
| // Chain of middleware to be invoked in order of their index | |
| middlewareChain := MiddlewareChain{ | |
| NewReqIDInterceptor(), | |
| ElapsedTimeInterceptor(), | |
| } | |
| router := mux.NewRouter() | |
| // Invoke all middlewares for indexHandler | |
| router.Path("/").Methods("GET").Handler(middlewareChain.Handler(indexHandler)) | |
| srv := &http.Server{ | |
| Addr: "0.0.0.0:8000", | |
| Handler: router, | |
| } | |
| if err := srv.ListenAndServe(); err != nil { | |
| fmt.Println(err) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment