NotFound配置必须在fiber.New()初始化时传入,不可后期覆盖;需显式调用c.Status(404),并确保StrictRouting和模板路径正确,否则404页面不生效。

NotFound 配置必须在 fiber.New() 初始化时传入
Fiber 的 NotFound 处理器不是运行时可覆盖的中间件,它只在 fiber.New() 构造应用实例时读取一次。如果你写了 app.Use(...) 或后续调用类似 app.Config().NotFound = ...,完全无效。
- 错误写法:
app := fiber.New(); app.Config().NotFound = func(c *fiber.Ctx) error { ... }—— 不生效 - 正确写法:必须作为
fiber.Config{}字段传入:fiber.New(fiber.Config{NotFound: my404Handler}) - 常见误判:以为注册了
app.Get("/404", ...)就能当 404 页面用 —— 实际上该路由只是个普通接口,和真正的 404 触发机制无关
状态码必须显式设为 404,否则浏览器看到的是 200
即使你返回了美观的 HTML,如果没调用 c.Status(404),响应状态码仍是默认的 200,搜索引擎和前端逻辑会当成成功响应处理。
-
NotFoundhandler 中务必第一行或至少在c.SendString()/c.Render()前调用c.Status(404) - 若用
c.Render("404", nil),模板渲染失败会 panic,导致整个 handler 崩溃并返回空白或 500;推荐包裹错误处理:
NotFound: func(c *fiber.Ctx) error {
c.Status(404)
if err := c.Render("404", fiber.Map{}); err != nil {
return c.SendString("<h1>⛔ 404 Not Found</h1>")
}
return nil
}
StrictRouting 导致 /users 和 /users/ 被视为不同路径
默认开启的 StrictRouting: true 是 404 频发的隐形推手。你注册了 app.Get("/users", ...),但用户访问 /users/(结尾带斜杠)就会直接命中 NotFound,连路由匹配都不进。
- 不要全局关掉
StrictRouting:虽然fiber.New(&fiber.Config{StrictRouting: false})能“解决”这个问题,但会破坏路径参数匹配逻辑(比如/users/:id和/users冲突) - 更安全的做法:显式注册两个版本:
app.Get("/users", ...)和app.Get("/users/", ...) - 或加一层重定向中间件,把带尾部斜杠的请求 301 跳转到无斜杠版本
模板渲染失败时容易静默降级为白屏
用 c.Render() 渲染 404.html 前,要确认三件事:文件存在、路径对、扩展名匹配。Fiber 不会报错提示“找不到模板”,而是直接 panic 或返回空响应。
- 检查
html.New("./views", ".html")的第一个参数是否是当前工作目录下的真实路径(go run main.go所在位置) - 确保文件名为
./views/404.html,而不是404.htm或views/404.html(少了个点) - 模板里引用的变量名必须首字母大写(如
{{.Title}}),fiber.Map{"title": "404"}里的title小写会导致渲染为空
NotFound 不触发时你还在检查 HTML 内容,而问题其实在初始化配置顺序、状态码遗漏或路径严格匹配这些底层行为上。


















