negroni 用了很久很久了, 一直觉得很不错, 目前为止核心源码只有 175 行, 很适合用来学习 Go

初始化

New 将传入的 handlers 构建成链表并保存的过程

type Handler interface {
    ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}

// middleware 是个单向链表
type middleware struct {
    handler Handler
    next    *middleware
}

// Negroni
type Negroni struct {
    middleware middleware // 单向链表
    handlers   []Handler // 用于存储所有传入的 handler
}

// New 就是用来构建 middleware 链表的方法
func New(handlers ...Handler) *Negroni {
    return &Negroni{
        handlers:   handlers,
        middleware: build(handlers),
    }
}

这里把传入的 handlers 保存并传给了 build 方法.

构建链表

// voidMiddleware 链表的终点
func voidMiddleware() middleware {
    return middleware{
        HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),
        &middleware{},
    }
}

// build 递归构建 middleware, 最终返回一个完整的链表
func build(handlers []Handler) middleware {
    var next middleware

    switch {
    case len(handlers) == 0:
        return voidMiddleware()
    case len(handlers) > 1:
        next = build(handlers[1:])
    default:
        next = voidMiddleware()
    }

    return middleware{handlers[0], &next}
}

Use实现

Use 本质上就是就是重新构建链表的过程

UseFunc, UseHandler, UseHandlerFunc 本质上就是将 http.Handler 转换为 negroni.Handler 的过程

// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
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)
}

// UseFunc adds a Negroni-style handler function onto the middleware stack.
func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
    n.Use(HandlerFunc(handlerFunc))
}

// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
func (n *Negroni) UseHandler(handler http.Handler) {
    n.Use(Wrap(handler))
}

// UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack.
func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) {
    n.UseHandler(http.HandlerFunc(handlerFunc))
}

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

Run

运行!!!

最终调用了标准库中的 http.ListenAndServe, 证明 Negroni 实现了标准库的 http.Handler 接口, 形成了链表调用

所以 handler 的顺序很重要, 一般 mux 路由, 都是在最后访入

// middleware 实现了 `http.Handler` 接口
func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
    m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
}

// Negroni 实现了 `http.Handler` 接口
func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
    n.middleware.ServeHTTP(NewResponseWriter(rw), r)
}

func (n *Negroni) Run(addr ...string) {
    l := log.New(os.Stdout, "[negroni] ", 0)
    finalAddr := detectAddress(addr...)
    l.Printf("listening on %s", finalAddr)
    l.Fatal(http.ListenAndServe(finalAddr, n))
}