iris中间件必须显式调用app.use()注册,否则不生效;需在run()/listen()前注册,按顺序执行;写响应后须立即调ctx.stopexecution(),否则引发panic或逻辑错误。

中间件注册必须用 app.Use(),不是自动生效
Iris 不会自动加载或执行任何中间件,所有拦截逻辑都得显式调用 app.Use() 注册。漏掉这一步,中间件函数压根不会被调用——哪怕你写了完整逻辑、路径也匹配,请求照样直通 handler。
常见错误现象:写了鉴权中间件,但所有接口都能无凭证访问;日志中间件没输出任何记录;CORS 头没加到响应里。根本原因几乎都是没调 app.Use()。
- 必须在
app.Listen()或app.Run()之前注册,否则服务启动后中间件不可用 - 多个中间件按注册顺序执行,比如
app.Use(logMiddleware, authMiddleware),log 先执行,auth 后执行 - 不能只写函数定义就以为生效,例如
func Cors(ctx iris.Context) { ... }不调app.Use(Cors)就等于没写
ctx.Next() 是控制流关键,不写或乱写会导致跳过 handler
ctx.Next() 的作用是把请求“往下传”,它本身不返回值、不阻断执行,只是推进中间件链。如果中间件里没写 ctx.Next(),后续所有中间件和最终的路由 handler 都不会执行;如果写了但前面已调 ctx.StopExecution() 或已写响应(如 ctx.JSON(401, ...)),ctx.Next() 仍会运行但无效,容易引发重复写响应 panic。
- 鉴权失败时:应先
ctx.StatusCode(401)+ctx.JSON(...),再立刻ctx.StopExecution(),确保ctx.Next()不被执行 - 日志中间件:必须在
ctx.Next()前记开始时间,在之后读ctx.ResponseWriter().Status()和耗时,否则拿不到最终状态码 - 别在
if分支里条件性调ctx.Next(),而是在所有分支外统一调,靠ctx.StopExecution()控制是否继续
中间件里写响应后必须调 ctx.StopExecution()
只要中间件里调了 ctx.StatusCode()、ctx.JSON()、ctx.Redirect() 或 ctx.WriteString(),就必须紧跟 ctx.StopExecution()。否则 Iris 会继续执行后续中间件和路由 handler,极大概率导致 “http: multiple response.WriteHeader calls” panic,或者业务逻辑被意外执行(比如用户未鉴权却进了数据库查询)。
- CORS 中间件中处理 OPTIONS 请求时:
ctx.StatusCode(204)后必须ctx.StopExecution(),否则ctx.Next()还会往下走 - 错误恢复中间件(recover):
ctx.JSON(500, ...)后不加ctx.StopExecution(),panic 恢复后仍会进原 handler,可能再次 panic - 路径重定向场景:
ctx.Redirect("/login", iris.StatusFound)后漏掉ctx.StopExecution(),会导致 /login 路由也被执行一次
中间件不能读取 ctx.Request().Body 多次
ctx.Request().Body 是单次可读流,中间件里一旦 io.ReadAll(ctx.Request().Body) 或类似操作,后续 handler 再读就是空字节。这对 JSON 解析、表单解析类中间件是硬伤。
- 需要解析 body 的中间件(如 JWT token 提取、签名验证),应先用
ctx.ReadBody()或ctx.ReadJSON(),它们内部会缓存并复用 body 数据 - 自定义读取时,务必用
ctx.Request().Body = ioutil.NopCloser(bytes.NewReader(buf))把 body 重置为可重读状态,否则下游 handler 会收不到数据 - 日志中间件想打原始请求体?别直接读
Body,改用ctx.FormValue()或ctx.URLParam()取 query/form 字段,更安全
ctx.Next() 和 ctx.StopExecution() 都得亲手安排。最容易被忽略的是——中间件里写完响应却不终止流程,这个问题在线上往往表现为偶发 panic 或逻辑错乱,排查时却很难联想到是中间件没停住。











