中间件必须显式注册,全局用app.use、路由级作为处理器参数传入,顺序决定执行顺序;需调用ctx.next()才能继续,否则中断链路;app.done为响应后钩子,不可修改响应。

中间件必须显式注册才能生效,Iris 不会自动加载或按名称匹配;全局中间件用 app.Use,路由级用 app.Get 等方法的参数列表传入,顺序决定执行顺序。
全局中间件:用 app.Use 注册,影响所有匹配路由
全局中间件在每次请求进入时都会执行,适合日志、鉴权、跨域等通用逻辑。它只对 app.Use 之后注册的路由生效,注册顺序无关紧要,但执行顺序严格按注册先后。
-
app.Use接收一个或多个iris.Handler类型函数,每个函数必须调用ctx.Next()才能继续后续中间件或处理器 - 若某个中间件未调用
ctx.Next()(比如直接返回错误),后续中间件和路由处理器将被跳过 - 不推荐在
app.Use中写 panic 恢复逻辑——应使用recover.New()这类专用中间件,否则可能掩盖真实错误 - 示例:
app.Use(func(ctx iris.Context) { fmt.Println("log: start") ctx.Next() // 必须有,否则后续全被阻断 })
路由级中间件:作为处理器参数传入,只作用于该路由
适用于仅需对特定路径启用的逻辑,比如 /admin 下的权限校验、/api/v1 下的限流。它和全局中间件可共存,执行时先走全局,再走路由级,最后是处理器本身。
- 写法是把中间件函数放在
app.Get、app.Post等方法的参数末尾,如app.Get("/user", authMiddleware, userHandler) - 多个中间件按从左到右顺序执行,每个仍需手动调用
ctx.Next() - 注意:如果路由级中间件里提前
ctx.StopExecution()或ctx.StatusCode(401)后未调用ctx.Next(),处理器不会运行 - 常见误用:把
ctx.Next()写在return之后,导致它永不执行
app.Done 是后置钩子,不是“响应中间件”
app.Done 注册的函数会在所有中间件和处理器执行完毕、响应已写出后触发,常用于清理资源或记录耗时,但它无法修改响应内容或状态码。
- 它不接收
ctx.Next(),也不参与请求处理链,所以不能用来做鉴权、重定向、Header 修改等操作 - 典型用途:关闭数据库连接、上报指标、打印结束日志
- 错误认知:“用
app.Done统一加 CORS Header”——不行,Header 必须在响应写出前设置,得用app.Use或路由级中间件 - 示例:
app.Done(func(ctx iris.Context) { fmt.Printf("done: %s %s in %v\n", ctx.Method(), ctx.Path(), time.Since(ctx.Values().GetDuration("start"))) })
中间件中访问上下文值和参数的注意事项
中间件函数签名固定为 func(iris.Context),所有请求数据都通过 ctx 获取,但不同阶段可用的数据范围不同。
-
ctx.Params().Get("id")在路由匹配完成后才有效,因此不能在app.Use的早期中间件中直接读取路径参数(除非你确定该路由一定带参数) -
ctx.FormValue("key")和ctx.ReadJSON()会消费请求 Body,多次调用会导致后续读取失败;如需复用,应先用ctx.Request().Body缓存并重置 -
ctx.Values().Set("user", u)可跨中间件传递数据,但要注意 key 名冲突;建议用自定义类型做 key,避免字符串硬编码 - 不要在中间件里启动 goroutine 并直接操作
ctx——ctx不是线程安全的,异步场景应提取必要字段后传参
最容易被忽略的是中间件执行链的“断裂风险”:漏掉 ctx.Next()、提前 ctx.StopExecution()、或在 panic 后没用 recover 中间件兜底,都会让请求无声失败。调试时优先检查中间件是否完整调用了 ctx.Next()。











