negroni本身是一个中间件,不过它也提供了拓展,以帮助我们更简单地实现自己想要的功能的中间件。那么,我们究竟该如何实现中间件,才能能够封装到negroni中,从而通过negroni来调用呢?可以通过一个简单的例子分析:
package main
import (
"fmt"
"net/http"
"github.com/urfave/negroni"
"github.com/phyber/negroni-gzip/gzip"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page!")
})
n := negroni.Classic() //创建一个negroni
n.Use(gzip.Gzip(gzip.DefaultCompression))
n.UseHandler(mux)
n.Run(":3000")
}
我们从negroni创建之后开始分析。n.UseHandler(mux)函数:
n.UseHandler(mux)
+func (n *Negroni) UseHandler(handler http.Handler)
|n.Use(Wrap(handler))
+func Wrap(handler http.Handler) Handler
|return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+func (n *Negroni) Use(handler Handler)
|n.handlers = append(n.handlers, handler)
|n.middleware = build(n.handlers)
+func build(handlers []Handler) middleware
|return middleware{handlers[0], &next}
调用n.UseHandler(mux)函数的过程中,同样也调用了n.Use()函数。说明negroni对于第三方中间件的使用是从n.UseHandler开始的。
接下来,一起来分析追踪过程中遇到的函数:
1. UseHandler
该函数返回将handler传递给Wrap()函数
func (n *Negroni) UseHandler(handler http.Handler) {
n.Use(Wrap(handler))
}
2. Wrap
该函数对handler进行封装,编程固定format的handler。
func Wrap(handler http.Handler) Handler {
return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
handler.ServeHTTP(rw, r)
next(rw, r)
})
}
3. Use
该函数则将handler添加到Negroni结构体中。其中,midlleware是一个链表。
func (n *Negroni) Use(handler Handler) {
if handler == nil {
panic("handler cannot be nil")
}
n.handlers = append(n.handlers, handler)
n.middleware = build(n.handlers)
}
+-----------------------------------------+
type Negroni struct {
middleware middleware
handlers []Handler
}
type middleware struct {
handler Handler
next *middleware
}
4. build
如果你了解C/C++,这个函数很好理解。它仅仅是一个迭代函数,实现了middleware链表的构建。
func build(handlers []Handler) middleware {
var next middleware
if len(handlers) == 0 {
return voidMiddleware()
} else if len(handlers) > 1 {
next = build(handlers[1:])
} else {
next = voidMiddleware()
}
return middleware{handlers[0], &next}
}
5. 对ServerHTTP的处理
同时,我们也要清楚Handler是一个接口,一个Handler对象必须实现Handler接口。Handler接口定义如下:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
negroni对ServeHTTP做了哪些处理呢?通过以下三个函数可以了解:
//函数类型,使用HandleFunc会调用
//func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)的实现
type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
//调用函数实现
func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
h(rw, r, next)
}
//实现ServerHTTP的封装
func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
}
接下来,我们追踪n.Run(“:3000”)函数:
n.Run(":3000")
+func (n *Negroni) Run(addr ...string)
|finalAddr := detectAddress(addr...)
+func detectAddress(addr ...string) string
|l.Fatal(http.ListenAndServe(finalAddr, n))
+func ListenAndServe(addr string, handler Handler) error
|......
negroni.Run解析address后,最终调用了http.ListenAndServe来实现服务器。这一步,才最终完成了服务器的搭建;所有的handler都交付给了http.ListenAndServe去实现。
关于negroni对于第三方中间件的使用就分析到这里了。
转自:blog.csdn.net/Kiloveyousmile/article/details/78740242