中间件

中间件就是在请求/响应周期中插入代码。中间件的常见用例是日志记录(Buffalo已经做过),身份验证请求等。
“已知”中间件包列表可以在https://toolkit.gobuffalo.io/tools?topic=m...找到。

中间件接口

中间件接口收入是buffalo.Handler,输出也是buffalo.Handler。

func MyMiddleware(next buffalo.Handler) buffalo.Handler {
  return func(c buffalo.Context) error {
    // do some work before calling the next handler
    err := next(c)
    // do some work after calling the next handler
    return err
  }
}

通过实现buffalo.MiddlewareFunc接口,我们可以实现控制整个应用的执行流程。

使用中间件

a := buffalo.New(buffalo.Options{})
a.Use(MyMiddleware)
a.Use(AnotherPieceOfMiddleware)

在上面的示例中,所有请求将首先通过MyMiddleware中间件,然后AnotherPieceOfMiddleware中间件,再进入最终处理程序。

注意:应用程序中定义的中间件由该应用程序中的所有路由和组自动继承。

在action中使用中间件

有时候,我们只想在一个操作上使用一个中间件,而不是在整个应用或者资源上。
因为一个中间件的定义就是接受buffalo.Handler并返回一个buffalo.Handler, 所以你可以包装任何buffalo.Handler

a := buffalo.New(buffalo.Options{})
a.GET("/foo", MyMiddleware(MyHandler))

当然,中间件也可以包含中间件。

a := buffalo.New(buffalo.Options{})
a.GET("/foo", MyMiddleware(AnotherPieceOfMiddleware(MyHandler)))

组中间件

a := buffalo.New(buffalo.Options{})
a.Use(MyMiddleware)
a.Use(AnotherPieceOfMiddleware)

g := a.Group("/api")
// authorize the API end-point
g.Use(AuthorizeAPIMiddleware)
g.GET("/users", UsersHandler)

a.GET("/foo", FooHandler)

在上面的例子中MyMiddlewareAnotherPieceOfMiddleware将在所有请求上有效,但AuthorizeAPIMiddleware只在/api/*路由上有效。

GET /foo -> MyMiddleware -> AnotherPieceOfMiddleware -> FooHandler
GET /api/users -> MyMiddleware -> AnotherPieceOfMiddleware -> AuthorizeAPIMiddleware -> UsersHandler

跳过中间件

有时候,我们希望将中间件添加到整个应用程序或组中,但是个别几个单独的处理程序除外。

// actions/app.go
a := buffalo.New(buffalo.Options{})
a.Use(AuthorizeUser)

// skip the AuthorizeUser middleware for the NewUser and CreateUser handlers.
a.Middleware.Skip(AuthorizeUser, NewUser, CreateUser)

a.GET("/users/new", NewUser)
a.POST("/users", CreateUser)
a.GET("/users", ListUsers)
a.GET("/users/{id}", ShowUser)

有效的中间件如下:

GET /users/new -> NewUser
POST /users -> CreateUser
GET /users -> AuthorizeUser -> ListUsers
GET /users/{id} -> AuthorizeUser -> ShowUser

重要信息:要跳过的中间件功能和操作功能必须是同一个Go实例

// EXAMPLE 2
app.Resource("/widgets", WidgetResource{})
app.Skip(mw, WidgetResource{}.Show) // WON'T WORK

wr := WidgetResource{}
app.Resource("/widgets", wr)
app.Skip(mw, wr.Show) // WORKS

因为两次WidgetResource{},是两个不同的实例。

跳过资源操作

有时候我们需要对某个资源设定中间件,但是需要跳过某些action。例如,允许guest用户查看List和Show操作上的资源,但在行动的其余要求授权。
没有加中间件之前是这样的。

app.Resource("/widgets", WidgetResource{})

加上中间件如下:

res := WidgetResource{}
wr := app.Resource("/widgets", res)
wr.Middleware.Skip(Authorize, res.Index, res.Show)

清除中间件

由于中间件是从其父级继承的,因此有时可能需要从“空白”中间件集开始
代码如下:

// actions/app.go
a := buffalo.New(buffalo.Options{})
a.Use(MyMiddleware)
a.Use(AnotherPieceOfMiddleware)

g := a.Group("/api")
// clear out any previously defined middleware
g.Middleware.Clear()
g.Use(AuthorizeAPIMiddleware)
g.GET("/users", UsersHandler)

a.GET("/foo", FooHandler)

对应的路由中间件为:

GET /foo -> MyMiddleware -> AnotherPieceOfMiddleware -> FooHandler
GET /api/users -> AuthorizeAPIMiddleware -> UsersHandler

列出应用的中间件

要获得应用程序正在使用的中间件的完整列表(通过分组细分),可以通过运行buffalo task middleware命令找到。

$ buffalo t middleware

-> /
github.com/gobuffalo/buffalo.*App.defaultErrorMiddleware
github.com/gobuffalo/buffalo.*App.PanicHandler
github.com/gobuffalo/buffalo.RequestLoggerFunc
github.com/gobuffalo/buffalo.sessionSaver
github.com/gobuffalo/mw-forcessl.Middleware.func1
github.com/markbates/coke/actions.App.func1
github.com/markbates/coke/actions.trackLastURL
github.com/markbates/coke/actions.TrackingCookie
github.com/markbates/coke/actions.App.func3
github.com/gobuffalo/mw-paramlogger.ParameterLogger
github.com/gobuffalo/mw-csrf.glob..func1
github.com/gobuffalo/buffalo-pop/pop/popmw.Transaction.func2
github.com/markbates/coke/actions.SetCurrentUser
github.com/markbates/coke/actions.SetPageTitle
-> /courses/{course_slug}
github.com/gobuffalo/buffalo.*App.defaultErrorMiddleware
github.com/gobuffalo/buffalo.*App.PanicHandler
github.com/gobuffalo/buffalo.RequestLoggerFunc
github.com/gobuffalo/buffalo.sessionSaver
github.com/gobuffalo/mw-forcessl.Middleware.func1
github.com/markbates/coke/actions.App.func1
github.com/markbates/coke/actions.trackLastURL
github.com/markbates/coke/actions.TrackingCookie
github.com/markbates/coke/actions.App.func3
github.com/gobuffalo/mw-paramlogger.ParameterLogger
github.com/gobuffalo/mw-csrf.glob..func1
github.com/gobuffalo/buffalo-pop/pop/popmw.Transaction.func2
github.com/markbates/coke/actions.SetCurrentUser
github.com/markbates/coke/actions.SetPageTitle
github.com/markbates/coke/actions.FindCourse
-> /admin
github.com/gobuffalo/buffalo.*App.defaultErrorMiddleware
github.com/gobuffalo/buffalo.*App.PanicHandler
github.com/gobuffalo/buffalo.RequestLoggerFunc
github.com/gobuffalo/buffalo.sessionSaver
github.com/gobuffalo/mw-forcessl.Middleware.func1
github.com/markbates/coke/actions.App.func1
github.com/markbates/coke/actions.trackLastURL
github.com/markbates/coke/actions.TrackingCookie
github.com/markbates/coke/actions.App.func3
github.com/gobuffalo/mw-paramlogger.ParameterLogger
github.com/gobuffalo/mw-csrf.glob..func1
github.com/gobuffalo/buffalo-pop/pop/popmw.Transaction.func2
github.com/markbates/coke/actions.SetCurrentUser
github.com/markbates/coke/actions.SetPageTitle
github.com/markbates/coke/actions.Authorize
github.com/markbates/coke/actions.AuthorizeAdmin

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
superwen
讨论数量: 0
发起讨论 只看当前版本


暂无话题~