Iris中间件必须返回func(ctx iris.Context),需显式调用ctx.Next()才能继续链路,错误写法如遗漏ctx.Next()或类Gin的return;全局用app.Use(),路由级用app.Get(path, middleware, handler);跨中间件传值唯一安全方式是ctx.Values().Set()/Get();终止链路必须用ctx.StopExecution()而非仅return。

中间件函数签名必须返回 iris.Handler
Iris 的中间件本质是符合 iris.Handler 类型的函数,签名固定为 func(ctx iris.Context)。它不能返回值,也不能用 return nil 或 return 提前退出逻辑——必须显式调用 ctx.Next() 才会继续执行后续处理器或中间件。
常见错误是写成类似 Gin 的 return 风格,或者漏掉 ctx.Next() 导致请求卡住:
// ❌ 错误:没有 ctx.Next(),后续路由不会执行
func authMiddleware(ctx iris.Context) {
if !isValidToken(ctx) {
ctx.StatusCode(401)
ctx.WriteString("Unauthorized")
return // 这里 return 不等于“结束中间件链”,只是退出当前函数
}
// 缺少 ctx.Next() → 路由 handler 永远不会运行
}
// ✅ 正确:检查后必须调用 ctx.Next()
func authMiddleware(ctx iris.Context) {
if !isValidToken(ctx) {
ctx.StatusCode(401)
ctx.WriteString("Unauthorized")
return
}
ctx.Next() // 关键:放行到下一个 handler
}
全局中间件用 app.Use(),路由级用 app.Get("/path", middleware, handler)
全局中间件对所有注册路由生效(包括静态文件),适合日志、CORS、基础鉴权;路由级中间件只作用于特定路径,适合权限细化或上下文预处理。
-
app.Use()添加的中间件在所有app.Get/app.Post等之前执行 - 若在
app.Get()中传入多个中间件,它们按顺序执行,最后才是路由 handler - 注意:静态文件路由(
app.HandleDir)也受app.Use()影响,若中间件里写了ctx.ResponseWriter().WriteHeader()后又调用ctx.Next(),可能触发 “header already written” 错误
示例:
app := iris.New()
// 全局日志中间件
app.Use(loggerMiddleware)
// 仅 /admin 下启用 auth
app.Get("/admin", authMiddleware, adminHandler)
app.Post("/admin/update", authMiddleware, updateHandler)
// 多个中间件串联(顺序敏感)
app.Get("/profile", loadUserMiddleware, validateProfileMiddleware, profileHandler)
ctx.Values().Set() 是跨中间件传递数据的唯一安全方式
Iris 不允许在中间件之间通过闭包变量共享状态(并发不安全),也不推荐用全局 map + 请求 ID 做上下文绑定。正确做法是统一使用 ctx.Values() —— 它底层是线程安全的 sync.Map,生命周期与当前请求绑定。
常见误区:
- 在中间件里直接修改
ctx.Request().Context():Iris 的iris.Context并不基于context.Context,改了也没用 - 用普通局部变量传值:不同中间件函数作用域隔离,无法访问
- 忘记类型断言:存的是
interface{},取的时候必须.Get("key").(MyType)或用.GetWeak("key")
示例:
func loadUserMiddleware(ctx iris.Context) {
userID := ctx.URLParam("user_id")
user, _ := findUserByID(userID)
ctx.Values().Set("user", user) // 存
ctx.Next()
}
func profileHandler(ctx iris.Context) {
user := ctx.Values().Get("user").(*User) // 取(需断言)
ctx.JSON(iris.Map{"name": user.Name})
}
中间件中调用 ctx.StopExecution() 可终止整个链路
当需要彻底中断请求(比如鉴权失败、重定向、返回错误页),不应只写响应再 return,而应调用 ctx.StopExecution()。它会跳过所有剩余中间件和最终 handler,防止后续逻辑意外执行(如数据库操作、日志记录等)。
典型场景:
- JWT 过期且无法刷新时,直接
ctx.StopExecution()+ 返回 401 - 请求 IP 在黑名单中,不记录日志也不进业务逻辑
- 灰度路由匹配失败,跳转到默认页面(此时需配合
ctx.Redirect())
对比:
// ❌ 可能导致后续 handler 仍被执行(尤其在多中间件链中)
if !isAllowed(ctx) {
ctx.StatusCode(403)
ctx.WriteString("Forbidden")
return
}
// ✅ 确保链路终止
if !isAllowed(ctx) {
ctx.StatusCode(403)
ctx.WriteString("Forbidden")
ctx.StopExecution() // 必须加这句
return
}
中间件顺序和 StopExecution() 的调用时机,是实际项目中最容易引发隐蔽 bug 的地方。尤其是嵌套中间件 + 异步逻辑混合时,建议在关键分支都显式加 StopExecution(),而不是依赖 return。


















