fiber中间件需调用c.next()放行,否则中断链;签名统一为func(*fiber.ctx) error;挂载顺序即执行顺序,支持全局或路径前缀匹配;带参中间件用闭包封装。

直接用 app.Use() 注册函数就行,不需要额外类型声明或包装——Fiber 的中间件和路由处理器签名完全一致,都是 func(*fiber.Ctx) error。
自定义中间件函数怎么写
核心就一条:必须调用 c.Next() 才能放行到下一个处理器;不调用就中断链。常见错误是忘了这句,导致后续路由/处理器完全不执行。
- 中间件函数里不能直接 return 响应(如
c.SendString())后还调c.Next(),会 panic:「body already written」 - 想拦截请求并提前返回,就别调
c.Next();想透传,就必须调 - 错误处理建议用
return c.Status(401).SendString("unauthorized")这类明确终止链的方式
示例:一个记录请求路径和方法的简单日志中间件:
app.Use(func(c *fiber.Ctx) error {
log.Printf("%s %s", c.Method(), c.Path())
return c.Next() // 必须有
})
中间件挂载位置影响执行顺序
app.Use() 的注册顺序 = 执行顺序,且对所有 HTTP 方法生效(GET/POST/PUT/DELETE 全覆盖)。它不是按路由匹配,而是按前缀路径「精确匹配或斜杠边界」触发。
-
app.Use("/api", middleware)→ 只匹配/api、/api/users、/api/v1/,不匹配/apis -
app.Use(middleware)(无前缀)→ 匹配所有请求,相当于全局中间件 - 多个
app.Use()按代码顺序执行,比如先鉴权、再日志、再限流,顺序反了可能让未鉴权请求也打日志
带参数的中间件怎么封装
用闭包返回真正的中间件函数,这是最常用也最灵活的方式。参数在闭包外捕获,中间件内部只接收 *fiber.Ctx。
- 不要把配置参数硬编码进函数体,否则无法复用
- 常见模式:
func(options Config) fiber.Handler { return func(c *fiber.Ctx) error { ... } } - 例如限流中间件可接受
maxRequests int和window time.Duration作为入参
示例:一个检查 Header 是否含指定 token 的中间件:
func requireToken(headerName, expectedValue string) fiber.Handler {
return func(c *fiber.Ctx) error {
if c.Get(headerName) != expectedValue {
return c.Status(403).SendString("forbidden")
}
return c.Next()
}
}
// 使用
app.Use(requireToken("X-Api-Key", "secret123"))
真正容易被忽略的是:中间件里读取的上下文数据(比如 c.Query()、c.Body())必须在 c.Next() 前完成,因为后续处理器可能改写或消费这些值;而写响应头(c.Set())可以在 c.Next() 前或后,取决于你想影响上游还是下游行为。











