第三章 HTTP协议基础:请求与响应结构、状态码详解、RESTful API设计原则
做接口联调,说白了就是在跟HTTP协议打交道。你发一个请求过去,对方回一个响应过来,中间要是出了岔子,整个联调就卡住了。我这些年带团队做仿真脚本,见过太多人连HTTP请求长什么样都没搞清楚,就开始写代码调接口——结果呢?一调一个坑。
这一章,咱们就把HTTP协议的基础掰开揉碎了讲清楚。你把这些搞明白了,后面联调出问题的时候,至少知道该往哪个方向查。
3.1 HTTP请求结构:你发出去的东西长什么样?
一个HTTP请求,说白了就四部分:请求行、请求头、空行、请求体。我习惯把这四部分记成「一行、一头、一空、一体」。
请求结构速览:
POST /api/v1/users HTTP/1.1 ← 请求行
Host: api.example.com ← 请求头
Content-Type: application/json ← 请求头
Authorization: Bearer xxxxxx ← 请求头
← 空行(必须要有)
{"name": "张三", "age": 28} ← 请求体
请求行里包含三个东西:方法、URI、协议版本。我在项目中遇到过有人把URI写成了绝对路径,结果服务端死活解析不了。记住,请求行里的URI是相对路径,不是完整的URL。
请求头是键值对,每个头一行。常见的像Content-Type告诉服务端你发的是什么格式的数据,Authorization用来做身份认证。嗯,这里要注意:头字段名是大小写不敏感的,但值可能是大小写敏感的。
空行很多人会忽略。我曾经排查过一个诡异的问题,请求体死活发不过去,最后发现是少了一个换行符。空行是请求头和请求体的分隔符,必须要有,不能省。
请求体不是所有请求都有。GET请求一般没有请求体,POST、PUT这些才会有。你想想看,GET是去拿数据,你带个请求体过去,服务端大概率会忽略掉。
3.2 HTTP响应结构:服务端回给你的东西
响应和请求的结构很像,也是四部分:状态行、响应头、空行、响应体。我个人习惯把响应体叫做「真正的答案」。
响应结构示例:
HTTP/1.1 200 OK ← 状态行
Content-Type: application/json ← 响应头
Cache-Control: no-cache ← 响应头
X-Request-Id: abc123 ← 响应头
← 空行
{"id": 1, "name": "张三", "age": 28} ← 响应体
状态行里的状态码是最关键的。200表示成功,404表示找不到资源,500表示服务端出错了。我建议你把常见的状态码背下来,联调的时候一眼就能看出问题出在哪一端。
响应头里有很多有用的信息。比如Content-Type告诉你返回的数据是什么格式,Cache-Control告诉你能不能缓存。我在项目中遇到过返回的Content-Type是text/html,但实际返回的是JSON数据——这就是服务端配置有问题。
响应体就是服务端给你的数据。格式可能是JSON、XML、纯文本等等。联调的时候,我习惯先看状态码,再看响应头,最后看响应体。这个顺序能帮你快速定位问题。
3.3 状态码详解:每个数字背后都有故事
状态码分五类,每类代表一种情况。我刚开始做联调的时候,记不住这么多状态码,后来发现其实常用的就那么十几个。
| 分类 | 范围 | 含义 | 常见状态码 |
|---|---|---|---|
| 1xx | 100-199 | 信息性响应 | 100 Continue, 101 Switching Protocols |
| 2xx | 200-299 | 成功 | 200 OK, 201 Created, 204 No Content |
| 3xx | 300-399 | 重定向 | 301 Moved Permanently, 302 Found, 304 Not Modified |
| 4xx | 400-499 | 客户端错误 | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found |
| 5xx | 500-599 | 服务端错误 | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable |
避坑指南:我曾经遇到过服务端返回200,但响应体里却是一个错误信息。这种「假成功」最坑人。所以联调的时候,不要只看状态码,还要看响应体里的业务状态码。很多API设计会在响应体里再放一个code字段,用来表示业务层面的成功或失败。
几个容易混淆的状态码:
- 401 vs 403:401是未认证,你没登录或者token过期了;403是已认证但没权限。我见过有人把这两个搞混,排查了半天才发现是权限问题。
- 404 vs 410:404是资源不存在,可能是路径写错了;410是资源曾经存在但现在被删除了。410用得比较少,但如果你看到它,说明资源是被主动删除的。
- 500 vs 502 vs 503:500是服务端内部错误,代码崩了;502是网关或代理出了问题;503是服务暂时不可用,比如过载了或者正在维护。
3.4 RESTful API设计原则:接口设计的好习惯
RESTful API,说白了就是一套接口设计的规范。你按照这个规范来设计接口,别人一看就懂,联调起来也顺畅。我这些年看过太多「野路子」接口,什么/getUserInfo、/deleteUserById,看着就头疼。
RESTful的核心原则:
- 资源导向:URL里只放名词,不放动词。比如
/users表示用户资源,而不是/getUsers。 - HTTP方法表示操作:GET是查,POST是增,PUT是全量更新,PATCH是部分更新,DELETE是删。你想想看,如果大家都用POST做所有操作,那接口文档得写多长?
- 状态码表达结果:成功用2xx,客户端错用4xx,服务端错用5xx。不要所有情况都返回200。
- 无状态:每个请求都包含所有必要的信息,服务端不保存客户端的状态。这样方便扩展,也方便做负载均衡。
RESTful API设计示例:
GET /users → 获取用户列表
GET /users/123 → 获取ID为123的用户
POST /users → 创建新用户
PUT /users/123 → 全量更新ID为123的用户
PATCH /users/123 → 部分更新ID为123的用户
DELETE /users/123 → 删除ID为123的用户
我在项目中遇到过有人把PUT和PATCH搞混了。PUT是全量替换,你传什么字段,服务端就存什么字段,没传的字段会被清空。PATCH是部分更新,你只传要改的字段就行。这个区别很重要,搞错了可能会把用户数据弄丢。
注意:RESTful不是银弹。如果你的业务场景很复杂,比如需要批量操作、事务性操作,RESTful可能就不太合适。这时候可以考虑用RPC或者其他协议。我见过有人硬套RESTful,结果接口设计得四不像,联调起来更痛苦。
3.5 本章知识体系
下面这张图把本章的核心知识点串起来了。你把它记在脑子里,联调的时候遇到问题,就知道该往哪个方向查。
这张图把HTTP协议分成了三条主线:请求结构、响应结构、状态码。底部是RESTful设计原则,它贯穿在请求和响应的设计之中。你联调的时候遇到问题,先看是请求的问题还是响应的问题,再看状态码属于哪一类,基本就能定位个七七八八了。
我的一个小习惯:每次联调之前,我都会先看一眼接口文档里的状态码定义。如果文档里没有明确列出所有可能的状态码,我会让后端补上。为什么?因为联调的时候,你看到404,如果文档里没写404是什么意思,你就得去问后端,一来一回半天就过去了。
好了,这一章的内容就到这里。HTTP协议是接口联调的基础,你把这些搞明白了,后面遇到问题就不会慌。记住:请求结构、响应结构、状态码、RESTful原则,这四个东西是你联调时的「四件套」。