iris 中无法直接修改 ctx.method(),因其为只读属性;应使用 ctx.exec("get", "/new/path") 实现服务端内部跳转,重走目标路由处理链,保持上下文完整且不触发全局中间件。

中间件里不能直接改 ctx.Method()
Iris 的 ctx.Method() 是只读属性,返回的是请求原始 HTTP 方法(如 "POST"),底层来自 *http.Request.Method。你无法在中间件中调用类似 ctx.SetMethod("GET") 这样的方法——Iris 没提供该接口,强行反射修改会破坏路由匹配逻辑,导致后续 handler 找不到或 panic。
真正有效的重写方式:用 ctx.Exec() 跳转到新路由
所谓“重写方法”,本质是让当前请求走另一条处理链,而不是篡改原始 method 字符串。Iris 提供了 ctx.Exec(),它能立即终止当前 handler 链,并以相同请求上下文(含 body、header、params)执行另一个已注册的路由。
- 必须确保目标路由已存在,且 method 匹配(比如你想“转成 GET”,就得有
app.Get("/new/path", handler)) -
ctx.Exec("GET", "/new/path")不会改变浏览器地址栏,也不发新请求,是服务端内部跳转 - 原请求 body 仍可被新 handler 读取(
ctx.ReadJSON()等照常工作),但注意 Body 只能读一次,若前面中间件已消费过,需提前重置 - 不触发新中间件链——
Exec()只执行目标路由绑定的 handlers,不会重新跑全局Use()中间件
典型场景:把 POST /api/legacy 透明转给 GET /api/v2/items
常见于兼容旧接口。不能靠前端改 method,也不能在 handler 里手动调另一个函数(会丢失 context 控制权)。
- 先注册目标路由:
app.Get("/api/v2/items", v2ItemsHandler) - 再写中间件,在匹配到
/api/legacy且 method 为"POST"时执行:if ctx.Path() == "/api/legacy" && ctx.Method() == "POST" { ctx.Exec("GET", "/api/v2/items") return } - 确保
v2ItemsHandler能从ctx.FormValue()或ctx.URLParam()正确提取原 POST 数据(因为Exec()不自动解析 body,原数据仍在 request stream 中)
别踩的坑:伪造 method 导致路由错乱
有人试图用 ctx.Request().Method = "GET" 强行修改,这会导致:
- 路由匹配阶段已结束,修改无效;后续
ctx.Method()仍返回原始值 - 若 handler 内部做了
if ctx.Method() == "POST"判断,逻辑依然走原始分支 - 破坏 Iris 内部状态,某些中间件(如日志、CORS 预检判断)行为异常
- 测试难覆盖:HTTP client 发的是 POST,你代码里却假装是 GET,断言和 mock 极易出错
真正的动态方法变更只能靠 Exec() 走明确定义的路由,而不是在运行时欺骗框架。











