Nginx URL Rewrite核心是区分内部重写与外部重定向:rewrite用于内部路径改写(地址栏不变)或301/302跳转,需严格把握last/break/redirect/permanent语义、正则匹配顺序及location执行阶段;return更适配简单状态码跳转;proxy_pass负责反向代理而非重定向。

直接用 middleware.Rewrite 最省事,但得注意匹配顺序和通配符写法;手动 http.Redirect 更灵活,但漏掉 return 会 panic。
用 Rewrite 中间件批量重定向 URL
这是最常用、也最适合做路径结构调整的方式。它在请求进入路由前就完成重写(不是响应阶段的 30x 跳转),不触发新请求,性能好。
-
middleware.Rewrite必须注册在e.Pre()阶段,不能用e.Use(),否则路由已匹配完毕,重写无效 - 键是匹配模式,值是目标路径;
*表示捕获任意字符,$1引用第一个捕获组 - 匹配是按字典序从上到下执行,所以更具体的规则(如
/old/about)要放在通配规则(如/old/*)前面 - 示例:
e.Pre(middleware.Rewrite(map[string]string{"/old": "/new", "/api/v1/*": "/v2/$1"}))—— 注意末尾斜杠是否一致,/api/v1/和/api/v1匹配行为不同
用 HTTP 30x 状态码做真实跳转
需要浏览器地址栏变化、或 SEO 友好跳转时,必须用 http.Redirect 或 c.Redirect()。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 在 handler 里调用
c.Redirect(http.StatusMovedPermanently, "/new-path")即可,Echo 会自动终止后续 handler 执行 - 如果自己用原生
http.Redirect(c.Response(), c.Request(), "/new", http.StatusFound),**必须紧跟return**,否则后续代码继续执行,大概率报write to body after headers sent - 别在中间件里无条件 redirect:比如想对未登录用户跳登录页,得先判断
c.Get("user") == nil,再 redirect,否则所有请求都被拦下 - 状态码选
http.StatusMovedPermanently(301)还是http.StatusFound(302)取决于是否希望浏览器缓存跳转结果
404 请求统一跳转到首页或自定义页面
Echo 没有内置 404_override 配置项(像 CodeIgniter 那样),得靠兜底路由 + 显式 redirect 实现。
- 把
e.GET("/*", func(c echo.Context) error { return c.Redirect(http.StatusFound, "/") })放在所有其他路由之后 - 这个
/*是最宽泛的匹配,必须最后注册,否则会吞掉你本意要处理的/api/*等路由 - 更稳妥的做法是:先注册全部明确路由,再用
e.HTTPErrorHandler拦截 404 错误,里面做 redirect —— 这样不会干扰正常 404 响应逻辑(比如 API 返回 JSON 404) - 示例:
e.HTTPErrorHandler = func(err error, c echo.Context) { if he, ok := err.(*echo.HTTPError); ok && he.Code == http.StatusNotFound { c.Redirect(http.StatusFound, "/404.html"); return } echo.DefaultHTTPErrorHandler(err, c) }
真正容易被忽略的是 Rewrite 的执行时机和匹配优先级——它发生在路由解析之前,但规则顺序和通配精度直接影响最终结果;手动 redirect 则常因忘记 return 导致服务 panic,而不是返回预期跳转。









