iris.context是中间件唯一上下文,须显式调用ctx.stopexecution()终止流程;中间件注册位置决定作用域,鉴权应限于api分组;options预检需显式路由;ctx.user()需手动setuser赋值。

iris.Context 是中间件执行的唯一上下文载体,所有拦截、修改、终止逻辑都必须围绕它展开。Iris 不自动管理中间件生命周期,也不强制校验响应状态,写错顺序或漏掉 ctx.StopExecution() 就会进业务逻辑——这是绝大多数 401/500 隐蔽错误的根源。
中间件注册位置决定作用范围
全局中间件(app.Use())只影响已注册的路由路径;Party 分组中间件(party.Use())只对分组内路由生效;单个路由中间件(app.Get("/path", m1, m2, handler))按顺序逐个执行。
常见错误是把鉴权中间件挂到 app.Use(),但登录接口 /login 也被拦住,导致无法获取 token。正确做法是:用 app.Party("/api").Use(authMiddleware),把认证限制在 API 路径下,静态页和登录页走独立分组。
多个中间件串联时,顺序不能颠倒:日志 → 认证 → 限流 → 业务 handler。一旦某个中间件调用 ctx.StopExecution() 或已写响应(如 ctx.JSON(401, ...)),后续中间件和 handler 就不会触发。
OPTIONS 预检请求必须显式路由注册
Iris 不像 Express 或 FastAPI 自动捕获预检请求,只靠中间件里判断 ctx.Method() == "OPTIONS" 是无效的——路由未匹配,中间件根本不会运行。
必须显式注册通配 OPTIONS 路由:
-
app.Options("*", func(ctx iris.Context) { ctx.StatusCode(204) })(开发阶段) - 若 API 分组在
/api下,还需加api.Options("*", ...),否则/api/users的预检会被 404 - 生产环境禁用
"*",改用白名单校验:if originInWhitelist(ctx.GetHeader("Origin")) { ctx.Header("Access-Control-Allow-Origin", ctx.GetHeader("Origin")) }
缺失 Access-Control-Allow-Methods 或 Access-Control-Allow-Headers 会导致前端报错 “Response to preflight request doesn't pass access control check”。
中间件里写响应后必须调用 ctx.StopExecution()
这是最常被忽略的硬性规则。Iris 不检查是否已写响应就执行 ctx.Next(),行为完全由你控制。
典型错误写法:
func authMiddleware(ctx iris.Context) {
token := ctx.GetHeader("Authorization")
if token == "" {
ctx.StatusCode(401)
ctx.JSON(map[string]string{"error": "missing token"})
ctx.Next() // ❌ 错误:仍会继续执行后续中间件和 handler
}
}
正确写法:
func authMiddleware(ctx iris.Context) {
token := ctx.GetHeader("Authorization")
if token == "" {
ctx.StatusCode(401)
ctx.JSON(map[string]string{"error": "missing token"})
ctx.StopExecution() // ✅ 必须加这句
return
}
ctx.Next()
}
注意:即使只调用 ctx.WriteString() 或 ctx.Redirect(),也必须跟 ctx.StopExecution(),否则后续逻辑仍可能执行。
ctx.User() 是空接口,需手动赋值才能用
ctx.User() 默认返回 nil,Iris 不自动从 session 或 JWT 解析并填充它。你得在认证中间件里主动调用 ctx.SetUser(user)。
例如 JWT 校验成功后:
user := map[string]interface{}{"id": userID, "role": "admin"}
ctx.SetUser(user)
// 后续 handler 中就能用 ctx.User().(map[string]interface{})["id"]
如果用了 app.Party("/admin") 并在该分组注册了中间件,但没在分组上注册路由(比如误写成 app.Get(...)),ctx.User() 依然为 nil——因为中间件根本没执行。
另外,ctx.SetUser() 只在当前请求生命周期有效,不跨请求,也不存入 session;要持久化用户态,还得配合 sessions 包手动存取 session.Set("user_id", userID)。











