iris中间件中参数读取需严格区分来源:路径参数用ctx.params().get(),查询参数用ctx.urlparam(),表单或json须手动调ctx.formvalue()或ctx.readjson(),混用则丢数据;鉴权等中间件必须调ctx.stopexecution()终止执行。

中间件里拿不到请求参数,不是框架坏了,是没走对入口——Iris 的 ctx.Params()、ctx.FormValue()、ctx.URLParam() 各管一摊,混用就丢数据。
路径参数必须用 ctx.Params().Get(),别碰 ctx.URLParam()
RESTful 路由如 /user/{id:uint64} 中的 id 是路径参数,不是 URL 查询参数。用 ctx.URLParam("id") 永远返回空字符串,因为它是专读 ?id=123 这种 query string 的。
-
ctx.Params().Get("id")才是正解;参数名大小写敏感,{ID:uint64}就得写Get("ID") - 强转类型要检查 error:
id, err := ctx.Params().GetUint64("id"),err != nil时不能直接用id - 想设默认值避免 panic,可用
ctx.Params().GetUint64Default("id", 0),但注意语义合理性(比如 ID 为 0 是否合法)
表单和 JSON 参数不能靠结构体自动绑定进中间件
Iris MVC 的结构体自动绑定(如 func(ctx iris.Context, user User))只在控制器方法生效,中间件里不支持。你在中间件里写 ctx.ReadJSON(&v) 或 ctx.FormValue("email") 是唯一可靠方式。
- 前端发的是
application/json?先确认ctx.Request().Header.Get("Content-Type")确实含application/json,再调ctx.ReadJSON(&v),否则静默失败 - 表单提交(
application/x-www-form-urlencoded或multipart/form-data)只能用ctx.FormValue("field"),别幻想结构体能自动塞进去 - 重复读
ctx.Request().Body会报http: read on closed response body——中间件里读过一次 JSON,后续 handler 别再调ReadJSON
中间件响应后必须调 ctx.StopExecution()
Iris 不像 Gin 那样自动 Abort,ctx.Next() 只是“继续往下走”,哪怕你刚写了 ctx.StatusCode(401) 并返回了 JSON,不调 StopExecution(),业务 handler 仍会被执行。
- JWT 鉴权中间件典型结构:
if err != nil { ctx.StatusCode(401); ctx.JSON(err); ctx.StopExecution(); return } - 漏掉
StopExecution()是线上最隐蔽的数据误操作源头之一:用户没登录,却进了删除接口 -
ctx.StopExecution()和ctx.Stop()效果一致,但前者语义更明确,推荐统一用它
中间件顺序决定参数可读性
参数解析类中间件(如日志、鉴权)如果放在 Body 解析之后,可能拿不到原始 body;但如果放太前,又可能因 Content-Type 未识别而跳过解析逻辑。
- 推荐顺序:日志/trace → 鉴权(需 header)→
ctx.ReadJSON或ctx.ReadForm(仅当需要提前校验时)→ 业务中间件 - 不要在中间件里手动
io.ReadAll(ctx.Request().Body),这会消耗 body 流,导致后续 handler 读不到 - 若真需多次读 body,得用
ctx.RecordRequestBody(true)开启记录,并通过ctx.GetRecordedRequestBody()复用
最常被忽略的一点:中间件里的参数读取行为,完全取决于请求头 Content-Type 和路由定义方式——不是“框架该怎么做”,而是“你告诉它怎么读”。写错一个 header 或路径宏,参数就消失得无影无踪,连 error 都不抛。











