Fiber的404需用app.Use()兜底中间件检测c.Route()==nil并返回自定义页,500需禁用fiber.Default()的Recover()、手动实现panic捕获并传参渲染;Nginx未转发请求或error_page劫持会导致请求根本未进入Fiber。

为什么直接访问不存在路径还是返回空白或默认Nginx页
因为Fiber本身不接管Web服务器层的404——它只处理「已进入Go应用、但路由未匹配或处理器panic」的场景。如果请求连index.go都没走到(比如Nginx直接判定/nonexistent.css不存在并返回404),Fiber压根不会执行任何代码。
常见表现是:访问/foo返回空白,curl -I看到状态码200;或者看到Nginx默认404页。这说明请求根本没进Fiber。
- 确认你的反向代理(Nginx/Apache)已把所有非静态资源请求转发给Fiber服务,例如Nginx中
location / { proxy_pass http://127.0.0.1:3000; } - 确保Fiber监听的是正确端口且被代理可达,用
curl http://localhost:3000/nonexistent本地直连测试是否触发Fiber错误页 - 禁用Nginx的
error_page 404指令,避免它劫持本该由Fiber处理的404
怎么用app.Use()捕获未匹配路由并返回404页面
Fiber没有@app.errorhandler(404)这类装饰器,它的404必须靠「兜底中间件」实现:在所有app.Get()等路由注册之后,加一个app.Use(),检查c.Route() == nil。
这是最可靠、最符合Fiber设计意图的方式,比依赖Recover()更精准——它专治路由未命中,不干扰真实panic。
- 必须放在所有
app.Get()、app.Post()之后,否则会被提前终止 - 示例写法:
app.Use(func(c *fiber.Ctx) error { if c.Route() == nil { return c.Status(fiber.StatusNotFound).Render("404", fiber.Map{}) } return c.Next() }) - 确保
views/404.html存在,且已通过app.Static()或fiber.Config{Views: ...}正确配置模板引擎
500错误为什么总不显示自定义页面,反而看到panic堆栈
因为Fiber默认启用Recover()中间件(尤其当你用fiber.Default()启动时),它会捕获panic并返回带堆栈的JSON或文本,而不是你写的500.html。
想走模板渲染路线,得自己接管panic处理逻辑,不能依赖默认恢复行为。
- 上线必须用
fiber.New()初始化,避免fiber.Default()自动注入Recover()和Logger() - 手动添加自定义recover中间件,在panic后调用
c.Status(fiber.StatusInternalServerError).Render("500", ...) - 注意:模板渲染本身也可能panic(比如
{{ .User.Name }}中.User为nil),建议在500.html里只用安全字段或加{{ with .Error }}{{ . }}{{ end }}
模板里怎么拿到错误详情(如status code、message)
Fiber的Render()不自动传error对象,你得手动塞进去。不像Django或Flask那样隐式提供$exception或e变量。
这意味着你要在中间件里显式构造数据结构,再传给模板。否则500.html里只能显示静态文案。
- 404中间件示例:
c.Status(fiber.StatusNotFound).Render("404", fiber.Map{"Code": 404, "Message": "Page not found"}) - 500中间件示例(配合自定义recover):
defer func() { if r := recover(); r != nil { c.Status(fiber.StatusInternalServerError).Render("500", fiber.Map{ "Code": 500, "Message": "Internal server error", "Detail": fmt.Sprintf("%v", r), }) } }() - 模板中用
{{ .Code }}、{{ .Message }}即可取值,无需额外配置
Use()和recover手动接管。最容易被忽略的是:Nginx层拦截、fiber.Default()的默认中间件、以及模板渲染自身出错导致二次崩溃。


















