Buffalo路由必须在app.Routes()中显式注册才生效,否则404且无日志;Handler类型须严格为func(c buffalo.Context) error;子路由、CORS预检、WebSocket升级、模板字段匹配等均需按规范处理。

路由注册是否真正生效了
Buffalo 的路由不是写进 app.GET() 就算完事,它必须被 app.Routes() 显式加载。常见错误是只改了 actions/app.go 里的 App() 函数,但忘了在 app.Routes() 里调用 app.GET("/path", Handler) —— 这会导致上线后 404,连日志都不报错。
检查方法很简单:启动服务后 curl -I http://localhost:3000/your-path,看返回状态码;或者加一句 log.Printf("routes registered: %+v", app.Routes().Routes())(放在 app.Serve() 前)确认路径是否在列表里。
-
Handler必须是func(c buffalo.Context) error类型,不能少返回值、不能多参数、不能用http.HandlerFunc - 别把路由定义分散到独立的
routes.go文件里——Buffalo 不扫描,只认app.Routes()函数体内写的 - 如果用了子路由(
g := app.Group("/api")),确保g.GET()调用在Group()块内,且Group()被包含在app.Routes()中
生产环境路由是否暴露了不该有的调试入口
开发时加的 /debug/*、/metrics、/swagger 等路由,在上线前必须移除或用环境变量控制。Buffalo 不自带环境感知路由开关,靠手动条件注册:
if env := buffalo.Env(); env == "development" {
app.GET("/debug/pprof/*x", pprof.Handler())
}
更危险的是模板渲染路由(如 GET("/", HomeHandler))被误配成健康检查端点——K8s 的 livenessProbe 若指向它,一旦模板编译失败或 Templates == nil,整个 Pod 会反复重启。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 健康检查必须走纯逻辑路由,比如
GET("/healthz", func(c buffalo.Context) error { return c.Render(200, nil) })</li> <li>禁止在生产路由中调用 <code>c.Render()依赖未预编译的模板,否则首次访问必 panic;上线前务必运行buffalo task dev:build或启用app.PrecompileTemplates() - 所有带数据库查询的路由,上线前确认已关闭
DB.Trace()类调试中间件
跨域和预检请求是否在路由层兜住了
前端发带 credentials: true 的请求时,如果后端路由没显式处理 OPTIONS,浏览器会直接拒绝,连 Network 面板都看不到响应。Buffalo 不自动回复预检,必须手动注册 app.Options() 路由。
最常漏掉的三件事:Access-Control-Allow-Credentials: true、Access-Control-Allow-Origin 不能是 *、Vary: Origin 没设——尤其后者,CDN 缓存预检响应后,不同源请求可能拿到错的头。
-
app.Options("/api/*x", func(c buffalo.Context) error { ... })的路径要覆盖所有 API 前缀,不能只写/api/users -
Access-Control-Allow-Origin必须动态匹配请求头里的Origin,硬编码域名只适合单个前端;白名单校验逻辑别写在中间件里,得放Optionshandler 内部 - 别依赖 CORS 中间件统一注入头——
OPTIONS请求不走完整中间件链,很多中间件根本不会执行
WebSocket 路由有没有绕过 Buffalo 中间件链
Buffalo 的 Context 包装了 ResponseWriter,而 WebSocket 升级要求响应头「一字不差」:必须有 Upgrade: websocket、Connection: Upgrade 和正确的 Sec-WebSocket-Accept。任何中间件提前调用 WriteHeader() 或写 body,都会导致升级失败,浏览器只显示 WebSocket connection to 'ws://' failed,无其他线索。
正确做法是:用原生 http.Handler 实现 upgrade,路由注册时跳过所有 app.Use()。
- 注册方式必须是
app.GET("/ws", websocketHandler),且websocketHandler是func(http.ResponseWriter, *http.Request)类型,不是buffalo.Handler - handler 内必须直接调
upgrader.Upgrade(w, r, nil),禁止用c.Response().Writer或c.Render() -
gorilla/websocket.Upgrader的CheckOrigin必须显式校验r.Header.Get("Origin"),设成return true是线上事故高发点
c.Render(200, r.HTML("user/show.html")) 看似没问题,但只要 show.html 里引用了 {{.user.Email}} 而结构体字段名实际是 EmailAddr,服务一启动就会 panic,且错误堆栈不指明是哪条路由触发的。建议上线前用 buffalo build --dry-run 配合预编译检查,比等用户报错再查快得多。


















