Buffalo 不原生支持 PATCH 语义,需手动注册 app.Method("PATCH", ...) 并自行处理 application/merge-patch+json 解析、中间件适配及反向代理配置,否则易遇 405/415 错误。

Buffalo 的 PUT 和 PATCH 路由注册方式相同,但框架本身不区分语义
Buffalo 没有为 PATCH 提供独立的路由宏(比如 app.Patch()),你只能用 app.Options() 或更通用的 app.Method() 手动注册。它的 app.Put() 本质只是对 app.Method("PUT", ...) 的封装,PATCH 同理——但框架不会帮你解析 application/merge-patch+json 或 application/json-patch+json 这类媒体类型。
常见错误现象:405 Method Not Allowed,因为没显式注册 PATCH 方法;或者 415 Unsupported Media Type,因为 Buffalo 默认只按 application/json 解析请求体,而 RFC 7396 明确要求服务器不能把 application/json 当作 application/merge-patch+json 处理。
- 必须用
app.Method("PATCH", "/users/:id", handler)注册,不能依赖app.Put() - 需手动检查
r.Header.Get("Content-Type"),确认是application/merge-patch+json或application/json-patch+json - 不能直接用
c.Param("id")后就调c.JSON(200, ...)——你得先读取原始 body,再选对应 JSON 补丁库解析
解析 application/merge-patch+json 需要自己集成第三方库
Buffalo 的 c.Request().Body 是标准 io.ReadCloser,但它的 c.Bind() 只支持完整结构体绑定(类似 PUT 场景),对部分更新的 merge patch 无效。你必须跳过 Bind(),用原生方式读 body 并交给专用库处理。
使用场景:用户只想改邮箱字段,body 是 {"email": "new@example.com"},而不是传整个 user 对象。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
- 推荐用
github.com/mattbaird/jsonpatch(支持 RFC 6902)或github.com/mattbaird/mergepatch(支持 RFC 7396) - 注意:Buffalo 的
c.Request().Body只能读一次,读完后要重置(用http.MaxBytesReader或临时 buffer 防止超限) - 别在 handler 里直接
json.Unmarshal到 struct —— merge patch 允许 null 字段表示删除,struct 绑定会忽略 null
Buffalo 的中间件链对 PATCH 请求无特殊适配
所有 HTTP 方法共用同一套中间件栈,比如 middleware.CORS、middleware.PopTransaction。这看似方便,实则埋坑:CORS 中间件默认放行 PUT,但未必放行 PATCH(取决于预检响应头 Access-Control-Allow-Methods 是否包含它)。
性能影响:每个 PATCH 请求仍会触发完整的 Pop ORM transaction 初始化、session 解析、CSRF 检查——哪怕你根本不用这些功能。
- 检查
app.Use(middleware.CORS())是否在app.Method("PATCH", ...)之前注册,否则 CORS 预检失败 -
PopTransaction会在每个请求开头开事务,即使你的PATCHhandler 根本不碰数据库 - 若想跳过某中间件,只能写自定义 wrapper,用
c.Get("skip_pop")标记后在中间件里判断,Buffalo 不提供 per-route 中间件开关
实际部署时 PATCH 很可能被反向代理或 CDN 拦截
很多旧版 Nginx、AWS ALB 或 Cloudflare 默认不转发 PATCH 请求,会直接返回 405 或降级成 POST。Buffalo 本身无法感知这一层拦截,错误日志里只显示 “method not allowed”,容易误判为路由问题。
容易踩的坑:本地 curl -X PATCH 正常,上线后 405;或者前端发 PATCH,后端收到的是 POST,body 还被篡改过。
- 在 Nginx 配置中显式添加
location / { proxy_method PATCH; }(实际需用proxy_pass_request_headers on;+ 确保underscores_in_headers on;) - Cloudflare 默认禁用
PATCH,需提交工单开通,或改用X-HTTP-Method-Override: PATCH(但 Buffalo 不自动识别该 header) - 用
curl -v -X PATCH http://your-api/users/123在生产环境直连服务 IP 测试,绕过所有代理,确认是否真为 Buffalo 层问题
PATCH 的支持停留在“能收能转”的最低层级,没有语义解析、无媒体类型协商、无中间件分级控制。如果你的业务强依赖 PATCH 的部分更新语义,与其花时间打补丁,不如换用 net/http + gorilla/mux 或 chi,它们对方法注册和 content-type 分发更透明,也更容易接入 OpenTelemetry 和 gRPC 网关。

















