19. HTTP 请求方法与 GET/POST 区别(热度 190 · 进阶)
Q: 常见 HTTP 方法有哪些?GET 和 POST 有什么区别?什么是 OPTIONS 预检?
A:
常见方法
| 方法 | 语义 | 幂等 | 安全 | 典型 |
|---|---|---|---|---|
| GET | 读取资源 | 是 | 是 | 列表/详情 |
| POST | 提交/创建(非绝对) | 否 | 否 | 表单、下单 |
| PUT | 全量替换 | 是 | 否 | 更新整个资源 |
| PATCH | 部分更新 | 可设计为是 | 否 | 改单个字段 |
| DELETE | 删除 | 是 | 否 | 删除资源 |
| HEAD | 只取响应头 | 是 | 是 | 探活、查元数据 |
| OPTIONS | 探测支持的方法 / CORS 预检 | 是 | 是 | 跨域预检 |
(“安全”指不应改变服务器状态;幂等指同一请求多次与一次效果相同。)
GET vs POST(语义层面,非绝对)
| 维度 | GET | POST |
|---|---|---|
| 语义 | 获取 | 提交/处理 |
| 参数位置 | URL query | 请求体(也可 query,但不推荐混用语义) |
| 缓存 | 可缓存 | 默认不缓存(可显式) |
| 幂等 | 是 | 默认否 |
| 书签/历史 | 可 | 一般不可 |
| 长度限制 | 协议不限制,实现/浏览器/服务器常有限制 | 一般可更大 |
| 安全 | 均不提供机密性;参数在 URL 可能进日志/Referer | body 相对不易进 URL 日志,但仍需 HTTPS |
| 编码 | application/x-www-form-urlencoded 等 | 多种:json、multipart/form-data 等 |
重要澄清: 传输层两者都可以用 TCP,都可以有 body(GET 有 body 少见且许多实现忽略),差别主要在语义、缓存、幂等与生态约定,不是“一个加密一个不加密”。
OPTIONS 与 CORS 预检
- 跨域是浏览器同源策略行为,服务端之间无“跨域”。
- 当请求 跨域且非简单请求 时,浏览器先发 OPTIONS 预检:
- 非简单请求典型:自定义头(如
X-Token)、Content-Type: application/json、方法 PUT/DELETE/PATCH 等。
- 非简单请求典型:自定义头(如
- 请求头常含:
OriginAccess-Control-Request-MethodAccess-Control-Request-Headers
- 服务器应答:
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers- 可选
Access-Control-Max-Age(预检结果缓存秒数) - 涉及 Cookie 时
Access-Control-Allow-Credentials: true,且 Origin 不能是*
- 简单请求(GET/POST + 简单头 + 限定 Content-Type)不触发预检,但仍可能有 CORS 响应头要求。
常见追问
追问 1:GET 和 POST 的本质区别?GET 参数有长度限制吗?
- 答题要点: 本质是语义(读 vs 写)、幂等与缓存差异;不是“一个安全一个不安全”。协议层对 URL/Body 无绝对长度上限,限制来自浏览器、服务器(如 Nginx
large_client_header_buffers)、负载均衡等实现。
追问 2:为什么 JSON 跨域容易触发 OPTIONS?
- 答题要点:
Content-Type: application/json不在“简单类型”白名单(简单多为 text/plain、multipart/form-data、application/x-www-form-urlencoded),且常配自定义头/非 GET-POST 语义,故预检。
追问 3:预检失败常见原因?
- 答题要点: 未返回正确的
Access-Control-Allow-*;方法/头不在允许列表;带凭证却Allow-Origin: *;缓存过期;网关剥了 CORS 头;OPTIONS 被 WAF/框架路由拦下。
易错点
| 易错说法 | 纠正 |
|---|---|
| 「GET 一定没有 Body」 | 可以有,但许多实现忽略;语义上应避免 |
| 「POST 一定安全」 | 与 HTTPS 无关;明文 POST 仍可被窃听 |
| 「POST 不能缓存」 | 可配置缓存,但默认少缓存 |
| 「OPTIONS 是业务查询接口」 | CORS 预检中主要是预检探询,可与 API 文档方法探测共用,注意路由 |
| 「跨域要改前端就能解决」 | 需服务器配合 CORS 头或同源/网关方案 |
与选择题对照
- 主库 150: 第 85 题(GET 获取资源)、第 84 题(HTTP 方法列表含 OPTIONS)、第 86/87 题(404 资源不存在、301 永久重定向;「方法不被允许」的 405 主库未出题,看本题「常见方法」表)、第 91/90 题(HTTPS 请求流程)。
- 补题 16: 无直接 OPTIONS 选择题;面试与前端联调高频。
- 口述联动: 选择题考方法语义;面试要幂等/缓存/CORS 预检与“跨域是浏览器行为”。
工程 / 抓包背景
- curl:bash
curl -X OPTIONS -H "Origin: https://app.example.com" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: content-type,x-token" \ -i https://api.example.com/v1/orders curl -I -X OPTIONS https://api.example.com/v1/orders - 浏览器: DevTools Network 过滤
preflight/OPTIONS;查看 CORS 报错文案。 - Nginx:nginx
add_header Access-Control-Allow-Origin $http_origin always; add_header Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS" always; add_header Access-Control-Allow-Headers "Authorization,Content-Type" always; if ($request_method = OPTIONS) { return 204; } - Wireshark:
http.request.method == "OPTIONS";观察预检是否先于真实请求。 - API 设计: 用 GET 查询、POST 创建、PUT/PATCH 更新、DELETE 删除;避免用 POST 仅因为“能传参”。