app.use()是fiber挂载中间件的唯一入口,不写前缀则全局生效,写前缀(如"/api")仅匹配该路径开头的请求,不匹配/apix等非边界路径,多use按代码顺序执行,组路由group是语法糖,底层仍转为use。

app.Use() 是挂载路由中间件的唯一入口
Fiber 没有“局部中间件”概念,所谓“局部”只能靠 app.Use() 的前缀路径控制范围。它不是可选 API,而是强制路径匹配机制:不写前缀就全局生效,写了前缀(如 "/api")就只匹配该路径开头的请求(/api/users、/api/v1/health),但不会匹配 /apix 或 /users/api。
常见错误是用 app.Get("/api", middleware, handler) 试图“绑定中间件到某个路由”,这实际注册的是终结点,middleware 只在这个 GET 请求里执行一次,无法复用、不能拦截 POST、也不参与中间件链调度——真正需要的仍是 app.Use("/api", middleware)。
-
app.Use(middleware)→ 全局,所有路径都走 -
app.Use("/admin", middleware)→ 仅/admin及其子路径(/admin/dashboard) -
app.Use("/public", static.New("./public"))→ 静态资源专用,注意前缀必须和 URL 完全一致 - 多个
app.Use()按代码顺序执行,顺序错会导致鉴权没跑就进限流、或日志漏记
局部拦截器必须靠路径前缀 + 显式 return 控制流程
所谓“局部拦截”,本质是在中间件函数内部判断 c.Path() 或 c.OriginalURL(),满足条件才放行,否则直接响应并 return。Fiber 不提供类似 Spring 的 excludePathPatterns,一切靠手写逻辑。
比如只对 /api/** 做参数校验,但排除 /api/public/**:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
app.Use(func(c *fiber.Ctx) error {
path := c.Path()
if strings.HasPrefix(path, "/api/") && !strings.HasPrefix(path, "/api/public/") {
// 校验逻辑
if !isValidParam(c) {
return c.Status(400).JSON(fiber.Map{"error": "invalid param"})
}
}
return c.Next()
})
- 别用
regexp.MatchString做高频路径判断,正则编译+执行开销大,strings.HasPrefix更快更安全 -
c.Path()是解析后路径(不含 query),c.OriginalURL()含完整 URL,按需选用 - 判断失败后必须
return响应,不能只调c.Status().Send()就结束函数——漏return会继续执行c.Next(),请求照进 handler
分组路由 app.Group() 是组织局部逻辑的推荐方式
比起在中间件里反复做路径判断,更清晰的做法是用 app.Group() 划分作用域,再把中间件挂到组上。它不改变匹配逻辑,只是语法糖,底层仍转为 app.Use(prefix, ...)。
例如:
api := app.Group("/api")
api.Use(authMiddleware)
api.Use(rateLimitMiddleware)
api.Get("/users", userHandler)
api.Post("/orders", orderHandler)
-
app.Group("/api")等价于app.Use("/api", ...),但语义更明确 - 组内注册的路由自动带上前缀,
api.Get("/users")实际匹配/api/users - 中间件注册顺序仍关键:如果
authMiddleware没把用户信息写入c.Locals,后面的rateLimitMiddleware就拿不到 role 做分级限流 - 不要嵌套太多层 Group,Fiber 不做深度合并,每层都是独立前缀拼接,容易出路径歧义
最容易被忽略的坑:中间件返回值与响应状态冲突
很多拦截器写着写着就变成“半截中间件”:状态码设了,但没发 body;或者发了 body,却忘了 return,导致 c.Next() 还是被执行。Fiber 一旦检测到响应头已写出(c.Response().StatusCode() != 0),就会跳过后续 handler,但中间件本身若没 return,仍可能继续执行无关逻辑,甚至 panic。
- 正确姿势:每次手动响应后,必须跟
return,哪怕只是return nil - 别在中间件里用
defer补发响应——它无法中断已开始的流程,且可能覆盖已发出的内容 - 测试时用 curl 直接打接口,别依赖前端跳转,避免因 302 重定向掩盖了中间件未生效的问题
- 如果用了
ctx.Status(403).SendString("forbidden")却收到空响应,大概率是漏了SendString()或调了SendStatus()这种只设状态不发体的方法










