HTTP GET vs POST
比较 HTTP GET 与 POST 的标准方法语义:GET 获取目标资源的当前表示且属于 safe/idempotent;POST 让目标资源按自身语义处理请求内容,通常不是 safe/idempotent。参数位置和缓存表现是实现/工程层差异,不是二者的第一性定义。
[!info] related notes
- 所属 MOC: HTTP 与前端网络请求 MOC
- 方法总览: HTTP 方法语义
- 缓存: HTTP 缓存
- 幂等: 接口幂等设计
- 安全: CSRF
HTTP GET vs POST
第一性区别:Method Semantics
GET
GET 请求的标准语义是传输目标资源当前选中的表示。
标准语义上:
- safe;
- idempotent;
- 响应默认具备可缓存语义,除非缓存指令另有规定。
POST
POST 请求让目标资源按照自身定义的语义处理请求中的表示。
常见用途:
- 提交表单;
- 创建由服务器分配标识的新资源;
- 触发 command/action;
- 追加数据;
- 登录或其他处理流程。
POST 的标准方法语义:
- 不属于 safe;
- 不保证 idempotent。
Safe 与 Idempotent 不一样
Safe
→ 按设计意图不修改服务器资源状态
Idempotent
→ 重复执行同一请求,预期最终效果与执行一次相同
因此:
GET
safe + idempotent
POST
normally unsafe + non-idempotent
服务端自己把某个 POST 做成幂等,属于应用层额外 contract,不会改变 POST 的通用方法语义。
Query 与 Body 不是第一性区别
常见 Web 实践:
GET
→ 参数放 query string
POST
→ 数据放 request body
但真正定义 GET/POST 的不是“数据放哪里”,而是 method semantics。
RFC 9110 对 GET request content 很保守:客户端不应随意生成 GET content,除非 origin server 已明确表示支持这种用法;中间层也可能不了解这种私有约定。
所以工程上应避免设计依赖 GET body 的通用 API。
敏感数据与 URL
URL 可能进入:
- browser history;
- access log;
- analytics;
- Referer;
- bookmark / copied link。
因此 credential、password、secret 等敏感内容不应因为“这是查询”就放到 URL。
POST body 也不等于加密;传输机密性仍依赖 HTTPS。
缓存
GET
GET 是 HTTP 缓存的主要方法。
GET
→ Cache-Control / Expires / validators
→ shared/private cache
POST
POST response 并非理论上绝对不可缓存。
规范允许在满足明确 freshness 等条件时缓存某些 POST response,但现实缓存实现主要集中在 GET/HEAD。
稳定心智模型是:
GET 天然处在缓存主路径;POST 不应依赖普通缓存基础设施默认帮你复用结果。
Retry
GET 是 idempotent,因此网络基础设施更容易安全重试。
POST 默认不幂等:
POST /payments
connection drops
客户端不能仅根据“没收到 response”推断服务端没有执行。
这类业务需要:
- idempotency key;
- unique constraint;
- operation ID;
- durable command state;
等额外机制。
POST 不等于 Create
创建资源只是 POST 的一个常见用途。
例如:
POST /login
POST /search
POST /jobs/{id}/cancel
POST /reports/generate
都可能合理。
GET 不能产生副作用吗
Safe method 的约束是设计意图不改变资源状态。
服务端仍可能写 access log、metrics 或 cache,这些 incidental side effects 不改变 GET 的 safe semantics。
危险的是:
GET /article?id=10&do=delete
把业务破坏性动作隐藏在 GET 中,会被 crawler、prefetcher、link checker 等自动访问触发。
学习检查
- GET 与 POST 的第一性区别为什么不是 query vs body?
- Safe 与 idempotent 分别是什么意思?
- 为什么 GET body 不适合作为通用 API contract?
- POST 为什么可以通过应用设计实现幂等,却仍不是标准幂等方法?
- 为什么 POST 不等于 Create?
- GET 为什么比 POST 更自然地进入 HTTP cache 基础设施?
- 为什么 HTTPS 而不是 POST 决定传输机密性?
- 给支付提交场景解释“请求超时但服务器可能已经执行”为什么需要 idempotency key。