iris中间件必须为func(iris.context)类型,否则启动panic;需调用ctx.next()继续执行,可用ctx.values()安全传值,路径过滤需手动判断ctx.path()。

中间件函数签名必须接收 iris.Context
Iris 的中间件不是任意函数,它必须符合 func(iris.Context) 类型。如果传入的函数参数不对(比如漏了 ctx,或类型写成 *http.Request),启动时会 panic,错误信息类似:middleware: expected func(iris.Context), got func(*http.Request)。
常见写法示例:
func authMiddleware(ctx iris.Context) {
token := ctx.GetHeader("Authorization")
if token == "" {
ctx.StatusCode(401)
ctx.JSON(iris.Map{"error": "missing token"})
return
}
ctx.Next() // 继续执行后续 handler
}
-
ctx.Next()是关键:不调用它,后续路由逻辑就完全被阻断 - 中间件里不能直接 return,除非你明确想终止请求(比如鉴权失败)
- 不要在中间件里重复调用
ctx.ResponseWriter().Write()—— Iris 会自动处理响应流,手动写可能引发http: response.WriteHeader called multiple times
app.Use() 注册全局中间件
app.Use() 添加的中间件对所有注册的路由生效(包括后续动态添加的),但不作用于静态文件服务(app.HandleDir 默认绕过中间件,除非显式启用)。
注意顺序:中间件注册顺序 = 执行顺序。比如:
app.Use(logMiddleware)
app.Use(authMiddleware)
app.Get("/api/user", userHandler)
请求进来时,先执行 logMiddleware,再 authMiddleware,最后 userHandler。
- 如果某个中间件没调用
ctx.Next(),后面的中间件和 handler 都不会执行 -
app.Use()不影响app.Any()或app.Handle()定义的路由,只要它们是通过同一app实例注册的 - 若要排除某条路由,得改用
app.Get("/xxx").Use(...)做局部注册
如何让中间件只对特定路径生效?
Iris 不提供「路径前缀自动过滤」的语法糖,得靠 ctx.Path() 或 ctx.GetCurrentRoute().Subdomain() 手动判断。
例如只对 /api/ 开头的请求做鉴权:
func apiOnlyMiddleware(ctx iris.Context) {
if strings.HasPrefix(ctx.Path(), "/api/") {
// 执行校验逻辑
if !isValidToken(ctx) {
ctx.StatusCode(403)
ctx.JSON(iris.Map{"error": "forbidden"})
return
}
}
ctx.Next()
}
- 别依赖
ctx.Request().URL.Path—— 它未经过 Iris 路由解析,可能含查询参数或未标准化 -
ctx.Path()返回的是路由匹配后的 clean path(已去除重复斜杠、解码) - 若用了子域名路由(如
app.Subdomain("admin.")),中间件内可通过ctx.Host()辅助判断
中间件里怎么共享数据给 handler?
用 ctx.Values().Set(key, value) 存,ctx.Values().Get(key) 取。这是最安全的方式,生命周期与当前请求绑定,线程安全。
反例:用全局 map + 请求 ID 做上下文存储 —— 容易泄漏、难清理、并发不安全。
- key 推荐用自定义类型(避免字符串冲突),例如:
type ctxKey string; const userIDKey ctxKey = "user_id" - handler 中取值时记得类型断言:
if id, ok := ctx.Values().Get(userIDKey).(int64); ok { ... } - 不要把数据库连接、logger 实例塞进
ctx.Values()—— 它们应该通过依赖注入或 app 作用域管理
ctx.Next()),整个请求就卡死或返回空响应,调试时建议加 defer 日志和 recover 包裹关键逻辑。











