需显式调用app.OnErrorCode注册错误处理器,且必须在app.Listen前完成;ctx.ViewData不自动继承,须手动传值;静态资源404不触发OnErrorCode;JSON接口需按Accept头或路径判断响应格式;panic需中间件recover捕获。

如何注册自定义错误页面(404/500等)
Iris 不提供全局“error.html”自动兜底机制,必须显式调用 app.OnErrorCode 或 app.OnAnyErrorCode 注册处理器。漏掉这步,哪怕模板文件存在,404 仍会返回默认纯文本响应。
- 只对已注册的 HTTP 状态码生效,比如没调用
app.OnErrorCode(404, ...),404 就不会走你写的模板 - 注册必须在
app.Listen之前完成,否则无效 - 模板路径需与
app.RegisterView中声明的根目录和后缀一致,例如注册了iris.HTML("./views", ".html"),那ctx.View("404.html")就得对应./views/404.html
为什么 ctx.View() 在错误处理器里不渲染变量?
因为 ctx.ViewData 不会自动继承到错误处理器上下文——每个请求生命周期独立,错误处理器是全新上下文。你得手动传值,或者改用 ctx.ViewLayout + 布局模板统一管理。
- 错误处理器中要显示动态信息(如错误码、路径),必须显式调用
ctx.ViewData("status", 404)、ctx.ViewData("path", ctx.Path()) - 如果多个错误页共用头部/尾部,建议用
ctx.ViewLayout("layouts/main.html")并在布局里用{{template "content" .}},再分别定义404.html、500.html的contentblock - 别依赖中间件往
ctx.Values()存数据并期望错误处理器能读到——它不共享
静态资源 404 和路由 404 怎么区分处理?
Iris 默认把所有未匹配路由都交给 OnErrorCode(404),但静态文件(如 /static/js/app.js)404 实际由 app.HandleDir 内部逻辑触发,不会进你的 OnErrorCode 回调。想统一处理,得自己拦截。
- 在注册静态目录前,加一个通配路由:
app.Get("/static/{file:path}", func(ctx iris.Context) { /* 检查文件是否存在,不存在则 ctx.StatusCode(404); ctx.View("404.html") */ }) - 或改用
app.FileServer并设置fs := app.FileServer(iris.Dir("./static"), iris.Options{ShowList: false}),再配合fs.NotFound自定义回调(注意:该字段仅在 v12.2.0+ 支持) - 更稳妥的做法是:前端构建时确保引用路径准确,后端只专注路由层 404;静态资源问题交给 Nginx 或 CDN 处理
JSON API 错误响应怎么避免跳转到 HTML 页面?
当接口期望返回 JSON 却触发了 OnErrorCode(400),而你在里面调用了 ctx.View,就会返回 HTML,前端解析失败。关键在于判断请求类型。
- 检查
ctx.GetHeader("Accept")是否包含"application/json",是则用ctx.JSON,否则用ctx.View - 示例:
if strings.Contains(ctx.GetHeader("Accept"), "json") { ctx.JSON(iris.Map{"error": "not found", "status": 404}) } else { ctx.View("404.html") } - 别假设所有客户端都带 Accept 头——移动端 WebView 或旧 curl 可能不带,可补充检查
ctx.Path()是否以/api/开头作为 fallback
真正容易被忽略的是:Iris 的错误处理器不捕获 panic,默认会返回 500 文本。如果业务逻辑里有未处理 panic(比如 map 写入 nil、空指针解引用),它根本不会走到你写的 OnErrorCode(500)。必须配合 app.UseRouter 或自定义中间件做 recover,再手动调用 ctx.StatusCode(500) 和 ctx.View("500.html")。


















