Golang 9行代码实现http中间件

176 阅读1分钟

简介

中间件(middleware)是责任链模式的一种实现,在后端常用于Request与业务代码之间的一些信息处理,如身份获取、权限校验、日志记录、响应处理等,有效对业务代码进行隔离,并使中间处理代码模块化,条理更清晰。

责任链模式的核心思想为:

  • 不同职责模块接收和返回的参数相同,便于模块之间的组合调用。
  • 最终业务代码作为 next 函数被包裹进职责模块组合的最深处。

实现:

type MidHandler func(func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request)

func (m MidHandler) Use(h MidHandler) MidHandler {
	return func(next func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
		return h(m(next))
	}
}

func (m MidHandler) Run(h func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
	return m(h)
}
  • 测试:
func main() {
	m := MidHandler(func(next func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
		return func(w http.ResponseWriter, r *http.Request) {
			fmt.Println("mid1")
			next(w, r)
		}
	}).Use(func(next func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
		return func(w http.ResponseWriter, r *http.Request) {
			next(w, r)
			fmt.Println("mid2")
		}
	}).Use(func(next func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
		return func(w http.ResponseWriter, r *http.Request) {
			next(w, r)
			fmt.Println("mid3")
		}
	})

	http.HandleFunc("/", m.Run(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("123")
	}))

	http.ListenAndServe(":8888", nil)
}
  • 测试结果:
mid1
123
mid2
mid3
  • 试试 Go 自带的 BasicAuth
MidHandler(func(next func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if _, password, ok := r.BasicAuth(); ok && password == "123456" {
			next(w, r)
		} else {
			w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
		}
	}
})

还在用数组存储中间件函数?那也太low了。