中间件链路控制依赖显式调用c.next(),不调则短路;常见错误是返回401后未return即调c.next(),导致响应重复写或panic,正确写法必须return中断执行。

中间件链路控制不是靠“自动流转”,而是靠你显式决定是否调用 c.Next() —— 调了才往下走,不调就停在当前中间件,后续所有 handler 都不会执行。
为什么写了 401 还进 handler?
最常见错误:在中间件里返回错误响应后,又顺手调了 c.Next(),还忘了 return。
-
c.Status(401).SendString("unauthorized")已经写出响应头和体,底层 fasthttp 不允许重复写 - 此时再调
c.Next(),Fiber 会继续调度,后续 handler 可能 panic、覆盖 body、或静默泄露数据 - 正确写法必须是:
return c.Status(401).SendString("unauthorized")——return是关键,它中断函数执行,c.Next()根本不会被碰到
中间件执行顺序严格按注册位置
不是“分组优先”或“路径越长越先”,而是代码从上到下逐行注册的顺序决定执行链。
- 全局
app.Use(logger)→ 全局app.Use(recover)→ 分组api.Use(jwtAuth)→ 路由级api.Post("/delete", ipWhitelist, handler) - 如果把
jwtAuth放在recover后面,那 JWT 解析 panic 就不会被 recover 捕获 - 分组内没调
Use(),该分组下的路由就完全不经过任何中间件 ——Group()本身不继承中间件,只是路径前缀容器
鉴权失败时不能依赖 c.Next() 跳过
Fiber 没有类似 Express 的 next('route'),也没有“跳过当前 handler”的语义。拦截 = 不调 c.Next() + 立即 return。
- 认证中间件(如 JWT)必须先于鉴权中间件注册,否则
c.Locals["user"]是 nil - 鉴权中间件查权限失败,直接
return c.Status(403).SendString("forbidden"),绝不能写c.Next() - 错误示例:
c.Status(403).SendString("no"); c.Next(); return——c.Next()已交出控制权,return来不及了 - OPTIONS、
/healthz等路径需显式放行,否则会被卡在鉴权环节
静态资源或黑名单中间件要小心 body 消费
一旦调过 c.Body() 或 c.BodyParser(),原始请求体就被读空,下游拿不到 —— 这不是 bug,是 fasthttp 的复用机制。
- 黑名单中间件需用
c.Request().Body()或c.Body()读原始字节,解析完若需透传,得手动c.Request().SetBodyRaw(bodyBytes) - 防盗链中间件只校验
Referer,但c.Get("Referer")可能为空或非法 URL,必须先判断再url.Parse(),否则 panic - 中间件挂载点必须在
static.New()之前,否则静态文件请求被直接响应,中间件根本没机会运行
真正难的不是写中间件,而是每一步都得想清楚:我这次要不要交出控制权?交出去之前,响应有没有被意外写出?body 还剩多少?—— 这些细节不验证,上线后就是静默穿透或 panic。











