第三章 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协议基础:知识体系 HTTP协议 请求结构 请求行:方法 + URI + 版本 请求头:键值对 空行:分隔符 请求体:数据 响应结构 状态行:版本 + 状态码 + 短语 响应头:元数据 空行:分隔符 响应体:返回数据 状态码 1xx:信息性 2xx:成功(200, 201, 204) 3xx:重定向(301, 302) 4xx:客户端错误(400, 401, 403, 404) 5xx:服务端错误(500, 502, 503) RESTful API设计原则

这张图把HTTP协议分成了三条主线:请求结构、响应结构、状态码。底部是RESTful设计原则,它贯穿在请求和响应的设计之中。你联调的时候遇到问题,先看是请求的问题还是响应的问题,再看状态码属于哪一类,基本就能定位个七七八八了。

我的一个小习惯:每次联调之前,我都会先看一眼接口文档里的状态码定义。如果文档里没有明确列出所有可能的状态码,我会让后端补上。为什么?因为联调的时候,你看到404,如果文档里没写404是什么意思,你就得去问后端,一来一回半天就过去了。

好了,这一章的内容就到这里。HTTP协议是接口联调的基础,你把这些搞明白了,后面遇到问题就不会慌。记住:请求结构、响应结构、状态码、RESTful原则,这四个东西是你联调时的「四件套」。

可可精品资料库