Revel框架中Redirect函数用于安全重定向,自动返回302状态码并终止当前action;支持绝对路径、命名路由及自定义状态码,需手动处理query参数;中间件中禁用http.Redirect除非显式return;URL重写需通过routes.conf或Router.Add配置,属内部转发;传参依赖Flash或query string。

Revel框架里用Redirect函数做外部跳转
Revel 的 Redirect 是最常用、最安全的重定向方式,它会自动返回 302 状态码(除非显式指定其他码),并设置 Location 响应头。调用后 Revel 会立即终止当前 action 执行,不会继续跑后续逻辑 —— 这点和 Gin/Echo 的 c.Redirect() 类似,但比手动写 http.Redirect 更可靠。
常见写法:
-
c.Redirect("/login")→ 跳到绝对路径 -
c.Redirect("App.Login")→ 跳到命名路由(推荐,解耦 URL 字符串) -
c.Redirect(301, "App.Home")→ 强制 301 永久跳转
注意:如果在 Init 或中间件里调用 Redirect,要确认当前 Controller 实例已初始化;否则可能 panic。另外,Redirect 不会自动保留 query 参数,需要手动拼接:c.Redirect("/search?" + c.Request.URL.RawQuery)。
避免在中间件中用http.Redirect漏掉return
Revel 中间件是链式执行的,如果你在中间件里绕过 Revel 的 Redirect,直接调用 http.Redirect(c.Response.Out, c.Request, "/login", http.StatusFound),但忘了 return,后续中间件和 action 仍会继续执行 —— 这会导致 “write to body after headers sent” 错误,因为响应头已经发出去了。
正确做法只有两个选择:
- 用 Revel 自带的
c.Redirect(它内部已处理 abort) - 手动调用
http.Redirect后,立刻return,且确保不再调用c.Result或写入 response body
典型错误现场:if !isAuth { http.Redirect(...); } // 忘了 return,后面还跟着 c.Render(...) → 必炸。
URL重写(非重定向)要用Router.Add或routes.conf预定义
Revel 不支持运行时动态 rewrite(像 Nginx 那种正则改 URI),它的“重写”本质是路由映射:把一个请求路径绑定到某个 controller action,浏览器地址栏不变。这属于内部转发,不是 HTTP 重定向。
实现方式有两种:
- 在
conf/routes里写:GET /old-path Controller.Action(直接复用已有 action) - 代码中注册别名:
revel.Router.Add(&revel.Route{Pattern: "/v1/*", Action: "API.Handle"})
注意:这类配置不会触发浏览器跳转,客户端看到的 URL 始终是原始请求路径。如果想让用户看到新 URL,必须用 c.Redirect,而不是改路由。
重定向时传参只能靠Flash或query string
Revel 的 Redirect 不支持像 Spring 那样直接带 model 数据跳转。想在跳转后显示提示信息(比如“登录成功”),得用 c.Flash.Out["message"] = "Welcome!",然后在目标页面的模板里读 Flash.Out.message。这是 Revel 内置的 session-backed 一次有效消息机制。
如果要传结构化数据,只能走 query string:
- 简单值:
c.Redirect("/result?status=ok&code=200") - 避免敏感信息暴露在 URL 中(如 token、密码)
- 长度受限(一般不超过 2KB),超长建议改用 Flash 或后端 session 存储
容易被忽略的一点:Flash 数据默认只在下一次请求生效,但如果重定向链太长(比如 A→B→C),中间多跳一次就丢了 —— 此时必须用 query 或服务端持久化。


















