Golang应用程序的HTTP服务器和路由器中间件构建器

103 阅读1分钟

你可以使用下面的例子,在Go应用程序中连锁HTTP服务器和路由器级别的中间件。一个中间件在每个请求中运行一次。服务器级别的中间件在每次请求到达时都会运行,无论调用的是哪个端点。然而,路由器级别的中间件是针对它所链接的端点运行的。

中间件

链中第一个添加的中间件最后运行。同时,服务器级别的中间件总是优先于路由器级别的中间件:

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
}

使用实例

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,
    ),
}

路由器

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) {
	// ...
}