beego支持自定義過濾中間件,例如安全驗證、強制跳轉等。
過濾器函數如下所示:
beego.InsertFilter(pattern string, position int, filter FilterFunc, params ...bool)
InsertFilter函數的有三個必填參數和一個可選參數。
(1)pattern
路由規則,可以根據一定的規則進行路由,如果你全匹配可以用*。
(2)position
執行Filter的地方,五個固定參數如下所示,分別表示不同的執行過程。
- BeforeStatic 靜態地址之前
- BeforeRouter 尋找路由之前
- BeforeExec 找到路由之后,開始執行相應的Controller
- AfterExec 執行完Controller邏輯之后執行的過濾器
- FinishRouter 執行完邏輯之后執行的過濾器
(3)filter
函數 type FilterFunc func(*context.Context)
(4)params
設置 returnOnOutput 的值(默認 true), 是否允許如果有輸出是否跳過其他 filters,默認只要有輸出就不再執行其他 filters。
是否重置 filters 的參數,默認是 false,因為在 filters 的 pattern 和本身的路由的 pattern 沖突的時候,
可以把 filters 的參數重置,這樣可以保證在后續的邏輯中獲取到正確的參數,
例如設置了 /api/*
的 filter,同時又設置了 /api/docs/*
的 router,那么在訪問 /api/docs/swagger/abc.js
的時候,
在執行 filters 的時候設置 :splat
參數為 docs/swagger/abc.js
,但是如果不清楚 filter 的這個路由參數,
就會在執行路由邏輯的時候保持 docs/swagger/abc.js
,如果設置了 true,就會重置 :splat
參數.
下面示例驗證用戶是否已經存在,應用於全部請求:
var FilterUser = func(ctx *context.Context) { _, ok := ctx.Input.Session("uid").(int) if !ok && ctx.Request.RequestURI != "/login" { ctx.Redirect(302, "/login") } } beego.InsertFilter("/*",beego.BeforeRouter,FilterUser)
這里需要特別注意使用 session 的 Filter 必須在 BeforeStatic 之后才能獲取,因為 session 沒有在這之前初始化。
還可以通過正則路由進行過濾,如果匹配參數就執行:
var FilterUser = func(ctx *context.Context) { _, ok := ctx.Input.Session("uid").(int) if !ok { ctx.Redirect(302, "/login") } } beego.InsertFilter("/user/:id([0-9]+)",beego.BeforeRouter,FilterUser)
過濾器實現路由
beego1.1.2 開始 Context.Input 中增加了 RunController 和 RunMethod, 這樣我們就可以在執行路由查找之前,在 filter 中實現自己的路由規則.
如下示例實現了如何實現自己的路由規則:
var UrlManager = func(ctx *context.Context) { // 數據庫讀取全部的 url mapping 數據 urlMapping := model.GetUrlMapping() for baseurl,rule:=range urlMapping { if baseurl == ctx.Request.RequestURI { ctx.Input.RunController = rule.controller ctx.Input.RunMethod = rule.method break } } } beego.InsertFilter("/*",beego.BeforeRouter,UrlManager)