Beego中间件必须显式调用web.InsertFilter注册才生效,且须在web.Run()前调用;路径匹配需精准(如"/api/"),执行时机选BeforeRouter或AfterExec最稳妥,函数签名严格为func(web.Context),中断用c.Abort()或c.StopRun()。

Beego 的中间件(Filter)不是“配一下就生效”的东西,必须手动注册、路径匹配要准、执行时机选对,否则写完根本不会跑。
web.InsertFilter 必须在 web.Run() 之前调用
这是最常踩的坑:把 web.InsertFilter 写在 web.Run() 后面,或者写在某个 controller 里 —— 完全不生效,连日志都不会打。
- 正确位置:通常放在
main.go的init()或main()函数开头,确保在web.Run()之前执行 - 错误示例:
web.Run(); web.InsertFilter("/api/*", web.BeforeRouter, myAuth)→ 这行代码永远不会被框架读到 - 如果项目用了
bee new生成结构,推荐统一写在main.go顶部,紧贴beego.Run()上方
路径匹配写错导致 Filter 不触发
web.InsertFilter 第一个参数是路径 pattern,它不是正则,也不是前缀匹配,而是 Beego 自己的简单通配规则:
-
"/*"匹配所有请求(注意开头的/) -
"/api/*"匹配/api/、/api/users、/api/v1/data,但不匹配/api(少斜杠) -
"/static/*"才能捕获/static/uploads/file.jpg;只写"/static"不会匹配任何子路径 - 静态资源默认走独立分支,若想拦截
/upload/*,pattern 必须显式写成"/upload/*",不能依赖全局"/*"顺带覆盖
选错执行时机:BeforeRouter vs BeforeExec vs AfterExec
Beego 提供多个过滤点,但高频、安全、不易出错的只有两个:
-
web.BeforeRouter:请求刚进来、还没做任何路由判断。适合鉴权、CORS 预检、记录 IP、拒绝恶意 UA。此时c.Ctx.Input.Param还没初始化,别试图取 URL 参数 -
web.AfterExec:Controller 的Get()/Post()已执行完,响应体已生成但未写出。适合加X-Response-Time、统一包装 JSON 响应、清理 session 临时数据 - 别碰
web.BeforeExec做权限检查:此时路由已匹配、Prepare()已运行,但部分上下文(如:id参数)可能尚未注入Input,容易 panic -
web.FinishRouter太晚,响应已写出,再改 header 或 body 无效
Filter 函数签名和中断逻辑必须严格符合
Beego 的 Filter 不是 “return next()” 风格,没有返回值,也不传 next 参数。是否中断,全靠主动调用方法:
- 函数签名只能是:
func(c *web.Context),多一个参数或少一个星号都会编译失败或 panic - 想终止流程并返回 401?用
c.Abort(401),它会跳过后续所有 Filter 和 Controller,直接写响应 - 想重定向?用
c.Redirect(302, "/login"),然后必须跟c.StopRun(),否则框架还会继续执行后续逻辑 - 想在 Filter 中存数据供 Controller 用?用
c.Ctx.Input.SetData("user_id", 123),Controller 里通过c.Ctx.Input.GetData("user_id")取
真正麻烦的从来不是写几行 Filter,而是路径 pattern 写漏了、注册顺序颠倒了、或者在 BeforeExec 里强行读 :id 导致空指针 —— 这些地方一错,debug 花的时间远超写逻辑本身。











