You can use example below to chain HTTP server and router level middlewares in Go applications. A middleware runs once per each request. A server level middleware runs every time a request arrives no matter which endpoint is called. However, a router level middleware runs against the endpoint it is linked to.


Middleware


The first added middleware in the chain runs last. Also server level middleware always take precedence over router level middleware.


package middleware

import (
"net/http"
)

type (
// srv represents multi layer server level middleware list and is dedicated
// Server function.
srv func(http.Handler) http.Handler
// rtr represents multi layer router level middleware list and is dedicated
// to Router function.
rtr func(http.HandlerFunc) http.HandlerFunc
)

func Server(h http.Handler, mid ...srv) http.Handler {
for _, m := range mid {
h = m(h)
}

return h
}

func Router(h http.HandlerFunc, mid ...rtr) http.HandlerFunc {
for _, m := range mid {
h = m(h)
}

return h
}

Example usage


Server


func Mid1(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, rq *http.Request) {
// Do something

h.ServeHTTP(rw, rq)
})
}

func Mid2(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, rq *http.Request) {
// Do something

h.ServeHTTP(rw, rq)
})
}

// This is how you wire them up.
s:= &http.Server{
Addr: ":8080",
Handler: middleware.Server(
someRouter,
Mid1,
Mid2,
),
}

Router


func Mid1(handler http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, rq *http.Request) {
// Do something

handler(rw, rq)
}
}

func Mid2(handler http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, rq *http.Request) {
// Do something

handler(rw, rq)
}
}

// github.com/julienschmidt/httprouter
r := httprouter.New()

// This is how you wire them up.
r.HandlerFunc(
http.MethodGet,
"/leagues/:id",
middleware.Router(
league.Get,
Mid1,
Mid2,
))

// This does not use any middleware.
r.HandlerFunc(
http.MethodPost,
"/leagues",
league.Post,
))

// league.Post
func Get(rw http.ResponseWriter, rq *http.Request) {
// ...
}

// league.Post
func Post(rw http.ResponseWriter, rq *http.Request) {
// ...
}