3、HTTP 协议基础:请求方法、状态码、请求头与响应头
说实话,HTTP 协议这东西,天天打交道。但你真让我讲透,我估计不少同学会卡在「GET 和 POST 到底啥区别」这种问题上。
我当年刚入行时,也犯过傻。有一次写接口,把所有操作都用了 GET,结果被运维大哥骂了一顿——「你 GET 请求还能删数据?!」嗯,从那以后,我才开始认真研究 HTTP 的请求方法。
3.1 请求方法:你用什么方式跟服务器说话?
HTTP 定义了多种请求方法,最常用的就四个:GET、POST、PUT、DELETE。说白了,就是你对资源要做什么操作。
| 方法 | 含义 | 幂等性 | 请求体 |
|---|---|---|---|
| GET | 获取资源 | 是 | 无 |
| POST | 创建资源 | 否 | 有 |
| PUT | 更新/替换资源 | 是 | 有 |
| DELETE | 删除资源 | 是 | 通常无 |
关键点:GET 请求的参数拼在 URL 里,有长度限制(浏览器一般 2KB 左右)。POST 的参数在请求体里,理论上没限制。但这不是最重要的区别——语义才是。
我见过不少新手把 POST 当 GET 用,或者反过来。你想想看,如果你用 GET 去创建一个订单,服务器返回 200 但订单没创建成功,那问题出在哪?语义不对。
3.1.1 GET:查东西
GET 是最简单的。浏览器输入网址回车,就是 GET。它不应该有副作用——也就是说,你刷新一百次,结果应该一样。
GET /api/users?page=1&size=20 HTTP/1.1
Host: example.com
3.1.2 POST:造东西
POST 用来创建资源。每次调用都可能产生不同的结果——比如你提交两次订单,会生成两个订单号。
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "张三",
"email": "zhangsan@example.com"
}
我的习惯:POST 请求一定要做防重复提交。我曾经在一个支付接口上吃过亏,用户连续点了两次「提交」,结果扣了两次钱。后来我加了幂等性校验,用唯一请求号去重。
3.1.3 PUT:改东西
PUT 是幂等的。你调一次和调一百次,结果一样。它通常用来全量更新资源。
PUT /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "李四",
"email": "lisi@example.com"
}
3.1.4 DELETE:删东西
DELETE 也是幂等的。第一次删掉资源,第二次再删,服务器应该返回 404 或者 204,但不会报错。
DELETE /api/users/123 HTTP/1.1
Host: example.com
3.2 状态码:服务器在说什么?
状态码是服务器给你的「回话」。我刚开始看状态码时,只记得 200 和 404。后来踩坑多了,才明白每个状态码都有它的脾气。
3.2.1 2xx:一切正常
- 200 OK:请求成功。最常用的。
- 201 Created:资源创建成功。POST 请求常用。
- 204 No Content:请求成功,但没返回内容。DELETE 常用。
3.2.2 4xx:你搞错了
- 400 Bad Request:请求格式不对。比如 JSON 解析失败。
- 401 Unauthorized:没登录。需要认证。
- 403 Forbidden:登录了但没权限。
- 404 Not Found:资源不存在。
- 405 Method Not Allowed:方法不支持。比如只允许 POST,你用了 GET。
- 429 Too Many Requests:请求太频繁。限流了。
避坑指南:我曾经在项目里把 401 和 403 混用了。结果前端判断「未登录」时,后端返回了 403,导致用户一直弹「权限不足」而不是跳转登录页。记住:401 是没认证,403 是认证了但没授权。
3.2.3 5xx:服务器炸了
- 500 Internal Server Error:服务器内部错误。最常见。
- 502 Bad Gateway:网关或代理出问题。
- 503 Service Unavailable:服务暂时不可用。比如过载或维护。
- 504 Gateway Timeout:网关超时。
5xx 错误,说白了就是后端出问题了。我建议你在接口文档里明确约定:4xx 是客户端问题,5xx 是服务端问题。这样排查起来快很多。
3.3 请求头与响应头:藏在信封上的信息
HTTP 头部就像信封上的地址和邮戳。你光看正文不够,还得看头信息。
3.3.1 常见请求头
| 请求头 | 作用 | 示例 |
|---|---|---|
| Content-Type | 告诉服务器请求体的格式 | application/json |
| Authorization | 携带认证信息 | Bearer xxx |
| Accept | 告诉服务器客户端能接收的格式 | application/json |
| User-Agent | 客户端标识 | Mozilla/5.0... |
| Cookie | 携带会话信息 | session_id=abc123 |
3.3.2 常见响应头
| 响应头 | 作用 | 示例 |
|---|---|---|
| Content-Type | 告诉客户端响应体的格式 | application/json; charset=utf-8 |
| Set-Cookie | 设置 Cookie | session_id=abc123; Path=/ |
| Cache-Control | 缓存策略 | no-cache, max-age=3600 |
| Access-Control-Allow-Origin | CORS 跨域设置 | * |
我的经验:Content-Type 这个头最容易出错。有一次前端传了 JSON,但 Content-Type 写成了 text/plain,后端解析直接报 400。排查了半天才发现是头写错了。所以,请求头和响应头一定要对齐。
3.4 知识体系图
下面这张图,是我自己梳理的 HTTP 协议基础结构。你看一眼,就能把请求方法、状态码、头部串起来。
嗯,这张图其实就讲了三件事:用什么方法、得到什么结果、头里带了什么信息。你把这三点串起来,HTTP 协议的基础就算拿下了。
总结一下:
- GET 查、POST 增、PUT 改、DELETE 删——语义要清晰
- 2xx 成功、4xx 你错、5xx 我错——责任要分明
- 请求头告诉服务器「我要什么」,响应头告诉客户端「我给你什么」——沟通要对齐
我个人习惯在项目初期就把这些约定写进接口文档里。别等到联调时才发现「哎,你这个状态码怎么返回的是 200 但 body 里是错误信息?」——那可就晚了。