buffalo 路由由目录结构、方法名、资源命名三者强约定驱动,必须用 buffalo g resource 生成资源,方法名仅限 list/show/create/update/destroy,路径前缀默认复数小写,api 版本需中间件统一拦截,自定义路由须走 app.get() 并遵守 context 生命周期。

Buffalo 的路由不是靠手写 app.GET() 堆出来的,而是靠目录结构、方法名、资源命名三者强约定驱动的。硬编码路由等于放弃 Buffalo 的核心价值,也埋下后期维护雷。
资源型路由必须用 buffalo g resource 生成
手动在 actions/ 下建 users.go 并写 List/Show 方法,不如直接跑命令:
buffalo g resource users name:string email:string
这一步会自动完成五件事:生成模型文件、迁移、控制器(含标准 CRUD 方法)、模板路径、以及把 UsersResource 注册进路由表。漏掉任意一环(比如没生成模板、或方法名写成 Index 而非 List),就会导致 404 且无提示。
- 方法名只能是
List、Show、Create、Update、Destroy—— 拼错一个字母,路由就失效 - 生成的路由前缀默认是复数小写(
/users),不能靠改文件名来变路径;要改就得用--skip-template手动控制,再补路由定义 -
buffalo routes输出里看不到 handler 名?说明资源没被正确加载,大概率是actions/app.go里漏了app.Resource("/users", &UsersResource{})
API 版本路由必须前置拦截,不能靠拼接字符串
Buffalo 默认不识别 /api/v1/users 这类带版本的路径——它只认 /users。想支持版本化,得在中间件层做统一拦截,而不是每个 Resource 都加前缀。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
在 actions/app.go 的 app.Use() 链中插入一个校验中间件:
app.Use(func(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
path := c.Request().URL.Path
if !strings.HasPrefix(path, "/api/v1/") {
return c.Error(404, errors.New("not found"))
}
return next(c)
}
})
- 别在
app.Resource("/api/v1/users", &UsersResource{})里硬写路径——这会导致c.Param()解析失败,因为 Buffalo 内部路由匹配时会把前缀剥离 - 所有 API 路由必须走这个中间件,否则 v2 上线后旧客户端调用 v1 接口会静默 fallback 到根路由
- 如果要用 gorilla/mux 外挂动态路由(比如从配置中心加载),必须把 Buffalo 的
app.Handler封装成http.HandlerFunc注入,不能动app.Routes()
自定义路由要避开 app.GET() 直接注册
临时加个 /healthz 或 /metrics?别写 app.GET("/healthz", HealthHandler)。这种写法绕过 Buffalo 的 Context 初始化流程,c.Session()、c.DB() 全不可用,还容易和资源路由冲突。
- 正确做法:在
actions/下新建health.go,定义HealthHandler(c buffalo.Context) error,然后在app.go中用app.Get("/healthz", HealthHandler) -
app.Get()和app.Resource()是同级注册方式,都走 Buffalo 的 Context 生命周期管理 - 如果 handler 不需要模板、DB、Session,纯返回 JSON,记得用
c.JSON(200, map[string]string{"status": "ok"}),别用c.Render() - 所有自定义路由的 path 必须以常量形式定义(如
const HealthPath = "/healthz"),避免散落的字符串字面量
最易被忽略的一点:Buffalo 的路由匹配发生在中间件执行之后。如果你在认证中间件里修改了 c.Request().URL.Path,后续路由就找不到对应 handler——这不是 bug,是设计使然。所有路径改写逻辑必须在中间件链最前端完成,且不能依赖 c.Param() 去取改写后的值。










