app.Use(path, subApp) 是挂载子应用的唯一正确方式,subApp 必须为 *fiber.App 实例,路径自动重写、裁剪,且推荐挂载点以斜杠结尾(如 /admin/)以支持深层嵌套。

app.Use(path, subApp) 是挂载子应用的唯一正确方式
Fiber 不支持类似 Express 的 app.use("/api", apiRouter) 那种“子路由树直接插入”的语义,但提供了等效且更明确的机制:app.Use(path, subApp)。这里的 subApp 必须是另一个 *fiber.App 实例(不是 *fiber.Router 或 Group),它会被作为“挂载应用”处理,路径匹配逻辑由 Fiber 内部的 mount 标志控制。
关键点在于:subApp 自身注册的所有路由,都会被自动重写为相对于挂载前缀的路径——这是 Use 的 mount 模式,和普通中间件模式有本质区别。
- 必须传
*fiber.App:传Group或Router会 panic,因为只有App有完整的路由表和Mount支持 - 挂载后路径自动裁剪:访问
/admin/users时,subApp内部收到的c.Path()是/users,不是/admin/users -
subApp仍可独立运行:调试时可直接subApp.Listen(":3001"),逻辑完全解耦
子应用里不能用 app.Get("/") 直接响应根路径
挂载后,subApp 的 "/" 路由实际匹配的是挂载点下的“空路径段”,比如 app.Use("/admin", subApp) 后,subApp.Get("/") 对应请求 GET /admin/(注意末尾斜杠),而非 /admin。StrictRouting 默认开启,所以这两者不等价。
常见错误是只写 subApp.Get("/", handler) 却收不到 /admin 请求,结果反复排查网络或代理配置。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 要同时支持
/admin和/admin/,需显式注册两条:subApp.Get("", handler)(匹配空段)和subApp.Get("/", handler)(匹配单斜杠) - 更稳妥的做法是统一重定向:在
subApp开头加一个中间件,对c.Path() == "/admin/"的请求做 301 跳转到/admin - 别在
subApp里注册带完整前缀的路由,例如subApp.Get("/admin/users", ...)—— 这会导致最终匹配路径变成/admin/admin/users
挂载点路径必须以斜杠结尾才能匹配子路径
app.Use("/admin", subApp) 和 app.Use("/admin/", subApp) 行为完全不同。前者只匹配 /admin 及其“精确前缀+边界”路径(如 /admin/users、/admin/login),但不匹配 /admin/foo/bar;后者因挂载点以 / 结尾,Fiber 会将其识别为目录式挂载,自动支持深层嵌套。
这个差异源于 hasPartialMatchBoundary 的实现:挂载点末尾是否为 /,决定了后续路径段是否被当作子路径处理。
- 推荐始终用带尾部斜杠的挂载点:
app.Use("/admin/", subApp),避免漏掉深层路径 - 如果坚持用无尾斜杠形式,需确保
subApp内所有路由都以/开头(如subApp.Get("/users", ...)),否则无法匹配 - 挂载点不能是通配符或正则,例如
app.Use("/v{version}", subApp)会失败——Use不支持动态前缀解析
子应用中间件与主应用中间件的执行顺序
挂载后,一次请求的中间件执行链是:主应用全局中间件 → 主应用挂载点中间件(即 app.Use("/admin/", ...) 的处理器)→ 子应用全局中间件(subApp.Use(...))→ 子应用路由级中间件 → 子应用 handler。
容易忽略的是:子应用内部注册的 subApp.Use("/api", ...) 这类带前缀的中间件,在挂载后实际生效路径是 /admin/api/*,而不是 /api/* —— 因为路径重写发生在整个子应用层级,不是逐层叠加。
- 子应用的
Use前缀是相对于它自己被挂载后的“根”,不是原始路径 - 若需跨子应用共享认证逻辑,应在主应用挂载点处统一加中间件,而非在每个
subApp里重复写Use(auth) - 子应用无法感知主应用的
c.Locals,除非你在挂载中间件里手动赋值:c.Locals("tenant_id", "xxx")
Group 和 Use(subApp) 的语义边界——前者只是分组注册,后者才是真正的 mount。一旦把 Group 当成子应用传给 Use,程序启动就会 panic,而错误信息只提示 “invalid type”,不会告诉你缺了 *fiber.App。


















