beego.InsertFilter必须在beego.Run()前注册,仅限main()开头或init()中;路径需加结尾斜杠如"/api/";BeforeRouter不拦截/static/,须用BeforeStatic配合路径前缀;中间件末尾须显式调ctx.Next()或ctx.Abort()。

beego.InsertFilter 必须在 beego.Run() 之前调用
注册过滤器晚了就等于没注册。常见错误是把 beego.InsertFilter() 写在某个 Controller 的 Prepare() 方法里,或者放在路由注册之后、beego.Run() 之后——此时框架已启动,过滤器永远不会执行。
正确位置只有两个:main() 函数开头,或 init() 函数中。多个过滤器按注册顺序执行,但阶段不同(如 beego.BeforeRouter 和 beego.BeforeStatic)互不干扰,不能靠“顺序”跨阶段控制流程。
- 别在
controllers/目录下任何 Controller 文件里注册过滤器 - 别在
routers/router.go的init()里注册——它通常在beego.Run()之后才被 import 触发 - 如果用了
bee run热重载,确保main.go的初始化逻辑不依赖未加载的包(比如 ORM 模型)
静态资源路径 /static/ 不走 BeforeRouter,必须用 BeforeStatic
很多权限中间件写在 beego.BeforeRouter 阶段,结果发现 /static/private/file.pdf 完全没被拦截——这不是 bug,是 Beego 明确设计:静态请求绕过整个路由系统,直通文件系统。
想拦静态资源,唯一入口是 beego.BeforeStatic,且必须显式用路径前缀注册:
-
beego.InsertFilter("/static/users/", beego.BeforeStatic, authCheckForStatic)才有效 - 在
BeforeStatic阶段,ctx.Input.Param()、ctx.Controller、c.Data全为 nil,不能调用ctx.Input.Crued()或ctx.Render() - 参数提取只能手动解析
ctx.Request.URL.Path,比如用strings.TrimPrefix(path, "/static/users/")
中间件里漏掉 ctx.Next() 或误用 return
Beego 中间件不是普通函数,而是控制流节点。ctx.Next() 表示“继续执行后续过滤器或进入 Controller”,不调它,链路就断了;只写 return,则当前函数退出,但后续逻辑照常执行,可能造成重复处理或状态错乱。
- 所有中间件函数末尾,只要没调
ctx.Abort(),就必须显式写ctx.Next() -
ctx.Abort(401, "Unauthorized")是标准终止方式,它会跳过后续所有过滤器和 Controller - 不要
defer ctx.Next()—— 它不是回调,是同步跳转,defer 会导致执行时机错乱 - 在
BeforeStatic阶段调ctx.Abort()后,必须手动写响应体(ctx.ResponseWriter.Write()),否则客户端收不到内容
路径匹配写错导致中间件不触发
Beego 的路径前缀匹配很严格:"/api" 和 "/api/" 效果完全不同。前者会匹配 /apixxx,后者才真正匹配所有以 /api/ 开头的路径(如 /api/v1/users)。
- 注册时务必加结尾斜杠:
beego.InsertFilter("/api/", ...),避免误匹配 - 别用
"/*"试图全局拦截 —— 它不匹配/static/,也不匹配根路径/(需额外注册"/") - 如果想同时覆盖 API 和静态资源,得注册两次:
"/api/"+beego.BeforeRouter,以及"/static/"+beego.BeforeStatic - 路径区分大小写,
"/API/"不会匹配/api/
BeforeRouter),一套给静态资源(BeforeStatic),因为它们的上下文能力、可用字段、甚至错误返回方式都不同。没人能绕开这点。


















