Buffalo中间件执行顺序严格按app.Use()调用顺序决定,session必须在Routes前注册并传store,CORS需在鉴权前,自定义中间件插logger后应使用Append而非Use。

中间件注册顺序错乱会导致 session、auth、CORS 全部失效
Buffalo 中间件执行顺序严格按 app.Use() 调用顺序决定,不是“谁重要谁在前”,而是“谁先注册谁先执行”。常见错误是把 session.Middleware() 放在 app.Routes() 之后,或把 middleware.CORS() 放在 auth 中间件之后——前者导致 c.Session() 始终返回 nil,后者让 OPTIONS 预检请求直接 401。
关键点:
-
app.Use()注册的中间件默认插在 Buffalo 内置中间件(recovery→logger→request_id)之前;若需插在它们之间(比如 logger 之后、request_id 之前),必须手动重写app.Middleware.Handlers - 鉴权类中间件(如自定义 token 校验)应放在
session.Middleware()之后、路由匹配之前,否则无法读取已解析的 session 数据 - CORS 中间件必须放在所有鉴权中间件之前,否则预检请求因缺少 token 被拦截,浏览器收不到
Access-Control-Allow-Origin头
session.Middleware() 必须在路由前注册且显式传入 store
c.Session() 返回 nil 的最常见原因,就是 session.Middleware() 没注册,或注册了但没传 store 实例。Buffalo 默认不启用任何 store,只提供空壳中间件函数。
正确做法:
- 开发环境可用内存 store:
app.Use(session.Middleware(session.NewMemoryStore())),但注意热重载时数据会丢 - 生产环境必须用 Redis:
store := redis.NewStore("localhost:6379", "", "0", ""),再传给session.Middleware(store) - 务必在
app.Routes()之前调用app.Use(),顺序错位会导致整个链路不生效 - Redis store 不校验连接,首次
c.Session().Save()才 panic,建议启动时加store.Ping()主动探测
如何把自定义中间件插到 logger 之后但不干扰 recovery
想让 traceID 或审计日志记录 request_id,又不想让它被 recovery 捕获 panic(即 panic 发生时它不该执行),就不能用 app.Use()——那会让它排在 recovery 前面。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
替代方案:
- 用
app.Middleware.Append(traceIDInjector),追加到整个中间件链尾,确保logger已记录原始请求、recovery已完成 panic 恢复 - 若需插在两个默认中间件之间(如
logger和request_id之间),Buffalo 不支持索引插入,只能清空app.Middleware.Handlers后手动重建链表,把默认中间件和你的中间件按需append() - 避免在中间件里做阻塞操作(如 HTTP 请求、DB 查询),它会在每个请求生命周期内同步执行
禁用无用中间件能显著降低冷启动延迟和内存占用
Buffalo 默认启用一整套中间件:cookie 签名、CSRF、HTTPS 重定向、gzip 压缩等。纯 API 项目若保留它们,不仅浪费资源,还可能引发意外行为(如 CSRF 中间件拒绝非表单请求)。
精简建议:
- API 项目中注释掉
app.Use(cookies.Secure())、app.Use(csrf.New())、app.Use(middleware.PopTransaction) - 移除
app.ServeFiles()和静态文件中间件,删掉assets/目录及构建脚本 - 确认只用
c.Render(200, r.JSON(...))输出,禁用模板引擎加载逻辑(避免 plush 解析开销) - 用
go run main.go替代buffalo dev进行联调,避开 watcher 和 asset 编译带来的隐式开销
真正难调的从来不是中间件本身,而是你没意识到 app.Use() 的调用顺序会同时影响 session 可用性、CORS 行为、日志内容和 panic 捕获范围——这四者在 Buffalo 里是同一根链条上的齿轮,动一个,其他全跟着转。










