通配路径必须显式使用/path/*格式,/path/或/path无法匹配子路径;c.param("*")提取通配部分,且通配路由优先级最低,需避免覆盖具体路由。

通配路径用 /path/*,不是 /path/ 或 /path
直接写 e.GET("/users", ...) 或 e.GET("/users/", ...) 都不会匹配 /users/123 或 /users/profile?tab=1。Echo 的通配必须显式带 * 后缀,且需配合 Any 或具体方法(如 GET)使用。
常见错误是以为 /users/ 能“自动继承子路径”,其实它只匹配字面量 /users/ 这个完整路径(末尾斜杠也算),其余全部 404。
-
e.Any("/users/*", handler)→ 正确:匹配/users、/users/、/users/1、/users/search?q=a -
e.GET("/users/*", handler)→ 也正确,但只响应 GET;POST /users/1 会 405 -
e.GET("/users/", handler)→ 错:仅匹配GET /users/,不匹配任何子路径 -
e.GET("/users/*/", handler)→ 错:*后不能跟斜杠,会导致 panic 或静默失效
/* 匹配到的路径怎么提取?用 c.Param("*")
通配部分(* 所代表的子路径)不是参数名,而是固定键 "*"。别试图写 c.Param("path") 或 c.Param("rest") —— 那些都为空。
例如请求 GET /api/v1/users/123/profile?edit=true,注册了 e.GET("/api/v1/*", h),则:
-
c.Param("*")返回"users/123/profile"(不含查询参数) -
c.Request().URL.RawQuery返回"edit=true" - 若需拼回完整子路径,得手动组合:
"/" + c.Param("*") + "?" + c.Request().URL.RawQuery
通配路由优先级最低,别让它挡住更具体的路由
Echo 内部按 Static → Param → Match any(即 /*)顺序匹配。这意味着 /users/:id 和 /users/new 都会先于 /users/* 被检查。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
但如果你把 /users/* 写在最前面,逻辑上不影响匹配结果;真正危险的是——
- 写了
e.GET("/users/*", fallbackHandler),却忘了注册/users/health这类运维路径,结果全被 fallback 拦截 - 误用
e.Any("/*", catchAll)放在最顶,导致所有未定义路由(包括/favicon.ico)都进 catchAll,掩盖真实缺失路由问题 -
/static/*和 Nginx 的location ^~ /static/冲突:如果 Echo 也处理/static/,就白费 Nginx 动静分离设计
代理场景下 /* 必须搭配 httputil.NewSingleHostReverseProxy
单纯用 e.Any("/service/*", proxyHandler) 不行,proxyHandler 得是标准 http.Handler,而 Echo 的 Context 不是。
正确做法是用 echo.WrapHandler() 封装反向代理实例:
usersURL, _ := url.Parse("http://localhost:8081")
usersProxy := httputil.NewSingleHostReverseProxy(usersURL)
e.Any("/users/*", echo.WrapHandler(usersProxy))
注意两点:
-
Director函数必须重写req.URL.Path,否则转发过去的是/users/123而非后端期望的/123 - 若后端依赖原始 Host 或
X-Forwarded-For,默认行为会丢掉这些头,得手动补
通配路径看着简单,但实际生效依赖三处对齐:注册写法、参数提取方式、以及是否与 Nginx 或代理逻辑形成预期外的覆盖或冲突。漏掉任意一环,请求就静默错位。










