• 根据 HTTP 规范,GET 用于信息获取,而且应该是安全的和幂等的。
  • 根据 HTTP 规范,POST 表示可能修改变服务器上资源的请求。
  • 首先是 “GET 方式提交的数据最多只能是 1024 字节”,因为 GET 是通过 URL 提交数据,那么 GET 可提交的数据量就跟 URL 的长度有直接关系了。而实际上,URL 不存在参数上限的问题,HTTP 协议规范没有对 URL 长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE 对 URL 长度的限制是 2083 字节(2K+35)。对于其他浏览器,如 Netscape、FireFox 等,理论上没有长度限制,其限制取决于操作系统的支持。注意这是限制是整个 URL 长度,而不仅仅是你的参数值数据长度。
  • POST 是没有大小限制的,HTTP 协议规范也没有进行大小限制

以上为标准答案,实际回答时可增加如下两条:

  • 首先是语义区别,GET 为获取,POST 为提交;(分清语义区别是为了更好的实现 RESTFul 风格 API)
  • 其次是 GET 请求只请求服务器一次,但 POST 会请求两次,第一次是 OPTIONS 方式请求为了确定服务器是否能够接收数据,第二次才是真的 POST 请求,将数据提交到服务器;

标准答案之外,还有几个更能体现理解深度的维度:幂等与安全的准确定义、报文结构差异、缓存与可见性、以及”POST 两次请求”说法的澄清。

语义层:安全与幂等

  • 安全(safe):请求不修改服务器状态。GET 被规范定义为安全方法,因此浏览器、CDN、爬虫才敢放心地预取和缓存 GET
  • 幂等(idempotent):同一请求执行一次与执行多次效果相同。GET、PUT、DELETE 幂等;POST 不幂等(提交两次订单就是两单)

这两个性质不是学术概念,而是基础设施行为的依据:缓存只缓存 GET、重试策略只自动重试幂等方法、网关去重依赖幂等键。RESTful 设计里”用对方法”本质上就是在向整条链路声明这些性质。

报文层:参数在哪、body 是什么

  • GET 的参数在 URL query 中,请求体为空;POST 的参数通常在 body 中(form/json/multipart)
  • 因此 GET 的参数会出现在浏览器历史、代理日志、access log、Referer 头里——敏感信息(密码、token)绝不应放 GET 参数,这是安全红线而非风格问题
  • body 让 POST 能承载二进制与大体积数据(文件上传只能 POST/PUT)
  • “GET 限制 2KB/POST 无限制”是浏览器与服务器的实现限制(IE 2083 字节、Nginx 默认 large_client_header_buffers),协议本身无规定;实践中 URL 超过 2K 就该考虑改 POST 或收敛参数

行为层:缓存、书签与”两次请求”

  • GET 可被缓存、可收藏为书签、可被预渲染;POST 响应默认不可缓存
  • 关于”POST 会请求两次,先 OPTIONS 再 POST”:这不是 POST 的特性,而是跨域 CORS 的预检(preflight)。只有跨域且请求”不简单”(如 Content-Type: application/json、带自定义头)时浏览器才先发 OPTIONS;同域 POST 或简单表单 POST 都只有一次请求。面试中把预检说成 POST 固有行为是常见误答
  • TCP 层面曾有”POST 先发头再发体导致两个包”的观察(某些浏览器行为),与”两次 HTTP 请求”是两回事,不应混谈

选型实践

场景 方法 理由
查询、搜索、分页 GET 安全幂等、可缓存、可分享
创建资源 POST 不幂等、body 承载新资源
全量更新 PUT 幂等、语义明确
局部更新 PATCH 语义精确
删除 DELETE 幂等
  • 查询条件复杂(嵌套对象、超长列表)时,用 POST 做查询虽违反语义但常见,权衡点是放弃缓存与可分享性;折中方案是 GET + 参数压缩/ID 化
  • 幂等性补救:POST 接口加幂等键(请求唯一 ID + 服务端去重),把”不幂等”变成业务可控

GET 与 POST 的区别,表层是参数位置与长度限制,里层是安全/幂等语义驱动的全链路行为差异(缓存、重试、预检、日志暴露面)。按语义选方法,让基础设施替你工作,而不是与之对抗。