:design

Go语言Web框架Tango中的中间件应用级别

Tango在创建之初就支持了全局中间件的支持,经过最近的改进,同时支持了Group级别和Route级别的中间件。下面我们就一起来看下这三种级别的中间件:

比如我们自定义了一个新的中间件:

func MyMiddleware() tango.HandlerFunc {
    return func(ctx *tango.Context) {
        ctx.Info("I'm a middleware")
        ctx.Next()
    }
}

全局中间件

全局中间件在任何一个请求调用时均会进行调用。用法如下:

t := tango.Classic()
t.Use(MyMiddleware())
t.Get("/", func() string {return "global"})

Group中间件

Group中间件在Group下匹配的路由被调用时会被调用。用法如下:

t := tango.Classic()
t.Group("/group", func(g *tango.Group) {
    g.Use(MyMiddleware())
    g.Get("/", func() string {return "group"})
})

Route中间件

Route中间件在该Route被调用时会被调用。如果有多个,会按照先后顺序调用。用法如下:

t := tango.Classic()
t.Get("/route", func() string {return "route"}, MyMiddleware())

中间件优先级

  • 全局中间件被先调用,Group中间件次之,最后是Route中间件
  • 相同级别的中间件,先加入的被先调用

Go语言Web框架Tango在Session中间件中的设计

Tango在创建之初的目标就是既有Beego的效率,又有martini的灵活中间件。因此Session也是在核心库 tango 之外作为官方中间件存在,地址是 tango-session

Session因为有着灵活的设计,因此可以完成很多我们希望的功能。首先看下Session中间件的选项:

type Options struct {
    MaxAge           time.Duration
    SessionIdName    string
    Store            Store
    Generator        IdGenerator
    Tracker          Tracker
    OnSessionNew     func(*Session)
    OnSessionRelease func(*Session)
}

其中我将要着重讲的是Store,Generator和Tracker。

Store

Store是一个接口,主要作用是存储Session中的内容,其定义如下:

type Store interface {
    Add(id Id) bool
    Exist(id Id) bool
    Clear(id Id) bool

    Get(id Id, key string) interface{}
    Set(id Id, key string, value interface{}) error
    Del(id Id, key string) bool

    SetMaxAge(maxAge time.Duration)
    SetIdMaxAge(id Id, maxAge time.Duration)

    Run() error
}

默认的内核自带了MemoryStore,这将会把所有Session内容保存在内存中。同时官方中间件中也提供了

这几种方式进行Session内容的存储。当然如果你愿意,也可以自己来实现一个Store。

Generator

Generator是一个接口,主要封装了SessionID的生成算法,其定义如下:

type IdGenerator interface {
    Gen(req *http.Request) Id
    IsValid(id Id) bool
}

默认的Generator是Sha1Generator,他是通过req.RemoteAddr,当前时间和随机字符串生成。 当然你也可以自定义更好的算法来生成SessionID。

Tracker

Tracker是一个接口,主要封装了Session的跟踪方式,其定义如下:

type Tracker interface {
    SetMaxAge(maxAge time.Duration)
    Get(req *http.Request) (Id, error)
    Set(req *http.Request, rw http.ResponseWriter, id Id)
    Clear(rw http.ResponseWriter)
}

默认的Tracker实现是CookieTracker,就是我们最常见的,将SessionID保存在cookie中,通过cookie来进行跟踪。Session中间件中也同时提供了HeaderTracker,支持将SessionID保存在自定义的Http Header中。当然你也可以自定义Tracker,比如通过URL参数来进行跟踪等等方式。

最后

看起来似乎很复杂,但是一般情况下都不需要去改变,你只需要

t := tango.Classic()
t.Use(session.New())
t.Run()