Beego中间件必须在beego.Run()前注册,否则不生效;拦截/static/路径须用BeforeStatic阶段,且需手动解析URL;路径匹配应写为"/api/"而非"/api",避免误匹配。

中间件没生效?先确认注册位置和时机
Beego 中间件必须在 beego.Run() 之前注册,否则完全不加载。常见错误是把 beego.InsertFilter() 放在 controller 初始化或某个 handler 里——此时框架已启动,注册无效。
正确位置是 main.go 的 init() 或 main() 函数开头,紧挨着 beego.BeeApp.RunMode = "dev" 这类配置之后、beego.Run() 之前。
- 路径匹配写成
"/api"而不是"/api/":前者会误匹配/apixxx,后者才真正表示“以 /api/ 开头” - 想拦截静态资源(如
/static/private/xxx.pdf),不能用BeforeRouter,必须用beego.BeforeStatic注册点 - 用
beego.Router("/api", &APIController{})注册的路由,中间件注册路径也得对齐前缀,比如"/api/",否则可能漏掉
日志打点不输出?检查 ctx.Next() 的调用位置
中间件函数里如果写了日志但没看到输出,大概率是 ctx.Next() 被提前调用,或者被跳过。Beego 的执行链是线性的:当前中间件不调 ctx.Next(),后续所有中间件和 controller 都不会执行。
典型错误写法:if !authOK { ctx.Abort(401); return } 后面没补 ctx.Next() —— 这没问题,因为 abort 本就终止流程;但若写成 if authOK { ctx.Next() },漏掉 else 分支,那未授权请求就静默跳过整个链,连 401 都不返回。
- 调试时建议在中间件开头和结尾都加日志:
log.Println("before filter:", ctx.Request.URL.Path)和log.Println("after filter:", ctx.ResponseWriter.Status) - 注意
ctx.ResponseWriter.Status在ctx.Next()前始终为 0,只有响应写入后才更新 - 不要在中间件里调
c.ServeJSON()或c.TplName—— 此时 controller 尚未初始化,c是*context.Context,不是*Controller
断点进不去?Beego 的中间件不支持 IDE 直接断点
Go 的 HTTP server 启动后是多 goroutine 并发处理请求,IDE(如 GoLand)默认只在主 goroutine 断点。你在中间件函数设的断点,大概率因 goroutine 切换而错过。
更可靠的方式是用日志 + 条件输出,而不是依赖 IDE 断点:
- 在中间件开头加
if strings.HasPrefix(ctx.Request.URL.Path, "/debug/") { log.Printf("DEBUG: hit middleware, method=%s", ctx.Request.Method) } - 用
runtime.Caller(0)打印当前文件行号,确认执行流确实走到这里 - 避免在中间件里直接 panic —— Beego 不自动 recover,会导致整个服务崩溃;必须手动
defer func() { if r := recover(); r != nil { log.Printf("panic in middleware: %v", r) } }()
为什么 /static/ 路径完全不进中间件?这是设计,不是 bug
Beego 对 /static/ 开头的请求做了特殊优化:它绕过全部路由和 filter 阶段,由内置静态处理器直读磁盘文件并返回。所以你在 BeforeRouter 或 BeforeExec 注册的任何中间件,对静态资源请求都不可见。
唯一能拦截它的入口是 beego.BeforeStatic,但它能力受限:没有 c.Data、c.TplName,甚至 c.Ctx.Input.Param() 多数情况下为空。你只能靠 c.Ctx.Request.URL.Path 手动解析路径,再用 c.Abort(403) 拒绝。
- 例如限制私有静态资源:
beego.InsertFilter("/static/private/", beego.BeforeStatic, checkPrivateStatic) - 在
checkPrivateStatic里不能用c.Input.Session.Get("user_id")判断登录态——session 可能未初始化,得改用 token header 或 cookie 手动解析 - 如果同时需要 API 权限 + 静态资源权限,就得写两套逻辑,分别注册到
BeforeRouter和BeforeStatic,无法复用
BeforeStatic)、以及 controller 上下文的缺失,都会让预期行为和实际执行出现偏差。别急着改逻辑,先确认注册点、路径前缀、和过滤阶段是否真的对得上。


















