fiber 默认不捕获 panic,因 recover 中间件默认关闭;需显式调用 app.use(fiber.recover()) 并置于路由注册前,否则 panic 仍导致 500 或空白响应。

为什么 Fiber 默认不捕获 panic
Fiber 的 Recover 中间件确实存在,但它默认是**关闭状态**。很多开发者以为像 Gin 那样加个 Recovery() 就万事大吉,结果线上 panic 仍直接导致 500 页面或空白响应——根本原因是没显式启用它,或者启用了但没放在路由链最前面。
更关键的是:Recover 只对当前中间件链生效,如果 panic 发生在 app.Get("/path", handler) 的 handler 函数里,而你没在该路由前挂 Recover,那它就完全不起作用。
正确启用 Recover 中间件的写法
必须在注册任何路由前,用 app.Use(fiber.Recover()) 全局启用;若只对某类路由启用(比如仅 API),则需手动组合:
- 全局启用(推荐):
app.Use(fiber.Recover())放在app.Get/app.Post之前 - 局部启用(如仅 /api/*):
api := app.Group("/api"); api.Use(fiber.Recover()); api.Get("/user", handler) - 自定义 recover 行为时,别直接覆盖
fiber.Recover(),而是传入配置:fiber.Recover(fiber.RecoverConfig{EnableStackTrace: true})
注意:fiber.Recover() 默认不会打印堆栈,设 EnableStackTrace: true 后才输出,但生产环境建议关掉,避免敏感信息泄露。
panic 被捕获后,怎么返回 JSON 而不是 HTML
Fiber 的 Recover 默认返回的是纯文本 "Internal Server Error",且 HTTP 状态码是 500。如果你的前端只认 JSON,这个响应会直接报解析错误。
必须自定义 Handler 字段,接管 panic 后的响应逻辑:
app.Use(fiber.Recover(fiber.RecoverConfig{
Handler: func(c *fiber.Ctx, err error) error {
// 不要直接 c.Status(500).JSON(...) —— 可能被后续中间件覆盖
c.Set("Content-Type", "application/json; charset=utf-8")
return c.Status(500).JSON(fiber.Map{
"code": 500,
"msg": "服务内部错误,请稍后重试",
"data": nil,
})
},
}))
重点:return c.Status(...).JSON(...) 必须带 return,否则中间件链可能继续执行;c.Abort() 不需要手动调,Recover 内部已处理。
recover 失效的三个典型场景
即使写了 Recover,以下情况它也无能为力:
- panic 发生在
fiber.New()初始化阶段(比如 Config 解析失败、端口被占),此时 App 实例都未创建成功,中间件根本没机会注册 - panic 在独立 goroutine 里发生(如
go func() { panic("xxx") }()),Recover只捕获当前请求 goroutine 的 panic - 使用了
os.Exit(1)或直接调用runtime.Goexit(),这些不是 panic,recover 完全不生效
最后一句提醒:Fiber v3 的 Recover 不会自动记录日志,出问题时得自己在 Handler 里加 log.Printf("[PANIC] %v", err),否则你连哪条请求崩了都不知道。











