Beego 中间件应通过 beego.InsertFilter("/api/", beego.BeeApp.FilterType, yourMiddleware) 实现仅拦截 /api/ 开头请求,需在 beego.Run() 前注册,结尾斜杠避免误匹配;静态资源须用 beego.BeforeStatic 注册;POST 限制需在中间件内判断 Method;panic 需手动 defer recover。

Beego 中间件如何只拦截 /api/ 开头的请求
Beego 的中间件默认是全局生效的,想只作用于特定路径(比如 /api/),不能靠中间件内部做 if r.URL.Path 判断后跳过——那样会漏掉 beego.BeforeStatic 等特殊阶段,且破坏中间件链的语义。正确做法是利用 Beego 提供的过滤点注册机制,配合路径前缀匹配:
- 使用
beego.InsertFilter("/api/", beego.BeeApp.FilterType, yourMiddleware),其中/api/是前缀匹配,自动覆盖所有以该路径开头的请求(包括/api/v1/users、/api/upload) - 注意结尾斜杠:
/api和/api/行为不同;后者更安全,避免匹配到/apixxx这类误伤 - 该注册必须在
beego.Run()之前完成,通常放在main.go的初始化块里 - 不推荐在中间件函数内手动检查
c.Ctx.Input.URI()后 return,因为此时ctx.Next()已执行一半,可能干扰后续 filter 或 controller 的状态
静态资源路径(如 /static/)为什么中间件不生效
直接在 beego.BeforeRouter 或 beego.BeforExec 注册的中间件对 /static/ 请求完全无效,这不是 bug,而是 Beego 的设计逻辑:静态文件请求绕过整个路由系统,由内置静态处理器直连磁盘响应。
- 必须改用
beego.BeforeStatic过滤点注册中间件,这是唯一能拦截静态资源请求的入口 - 例如限制私有静态文件访问:
beego.InsertFilter("/static/users/", beego.BeforeStatic, authCheckForStatic) -
beego.BeforeStatic中的ctx不含完整 controller 上下文(如c.Data为空),只能依赖c.Ctx.Request和c.Ctx.ResponseWriter - 若同时需要路由级权限控制 + 静态资源权限控制,得写两套逻辑,分别注册到
BeforeRouter和BeforeStatic
如何让中间件只对 POST 请求生效
Beego 没有内置的 HTTP 方法过滤语法,但可以在中间件中快速判断并短路:
- 在中间件函数开头加判断:
if ctx.Ctx.Request.Method != "POST" { ctx.Next(); return } - 不要用
strings.EqualFold或正则,==足够快且安全 - 注意:如果该中间件还承担了 body 解析(如
ParseForm()),必须确保只在 POST/PUT/PATCH 等可带 body 的方法中调用,否则会阻塞 GET 请求读取 - 若需组合多个条件(如仅限
/api/login的 POST),优先用InsertFilter("/api/login", ...)定位路径,再在函数内判断 method,比全量判断路径+method 更高效
中间件里 panic 恢复必须手动 defer recover
Beego 的 recoverpanic 中间件只捕获 controller 层 panic,对自定义中间件内部抛出的 panic 无感。一旦中间件 panic,整个请求会直接 500,且堆栈不进日志。
- 每个中间件函数开头都应加:
defer func() { if err := recover(); err != nil { log.Printf("middleware panic: %+v", err) } }() - 不要试图在中间件里
recover后继续ctx.Next()—— 状态已损坏,应直接写错误响应并 return - 如果中间件依赖外部服务(如 Redis、DB),建议加超时控制(
context.WithTimeout),避免 goroutine 泄漏 - 特别注意 multipart 场景:在中间件里调用
r.ParseMultipartForm前,务必先设r.MaxMemory,否则攻击者可耗尽内存
Beego 中间件的路径匹配和生命周期阶段是强耦合的,错配过滤点或混用判断逻辑,比写错业务代码更容易引发静默失效。











