HTTP 报文结构

HTTP/1.1 是用可读文本一问一答的请求—响应(Request-Response)协议。我们把请求报文和响应报文扒开看看里面到底长什么样。

请求报文长什么样?

浏览器请求 /book?id=1 时,发出去的原始 HTTP/1.1 请求报文是这样的:

GET /book?id=1 HTTP/1.1
Host: books.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, deflate
Connection: keep-alive

从上往下固定分四块:

  1. 请求行(Request Line):第一行 GET /book?id=1 HTTP/1.1,用空格隔开请求方法(GET)、请求目标(/book?id=1)和协议版本(HTTP/1.1)。
  2. 请求标头(Request Headers):紧接着的一行行 字段名: 字段值,比如指明目标站点的 Host、声明浏览器型号的 User-Agent、声明支持压缩格式的 Accept-Encoding。
  3. 空行(CRLF,\r\n):极其重要的一行空行,用来告诉服务器“请求头到这儿结束了,下面全是请求体”。
  4. 请求体(Request Body,可选):客户端提交的数据。GET 请求一般没有请求体;POST 和 PUT 请求会把表单数据、JSON 或上传的文件放在空行后面。

响应报文长什么样?

服务器回传的响应报文结构完全对称:

HTTP/1.1 200 OK
Server: biqu-web
X-App-Version: 3.2.1
Content-Type: text/html; charset=utf-8
Content-Length: 1024

<!doctype html>
<html>
  <body>...</body>
</html>
  1. 状态行(Status Line):第一行 HTTP/1.1 200 OK,包含协议版本、三位状态码(200)和原因短语(OK)。
  2. 响应标头(Response Headers):比如告诉浏览器正文是什么格式的 Content-Type,告诉浏览器正文有多长的 Content-Length。很多正规网站还会在响应头里加上安全策略头:
    • Strict-Transport-Security(HSTS):强制浏览器以后只准用 HTTPS 访问。
    • X-Content-Type-Options: nosniff:不准浏览器瞎猜响应内容类型,老老实实按 Content-Type 处理。
    • X-Frame-Options: DENY:不准别的网站用 <iframe> 嵌这个页面,防点击劫持。
    • Content-Security-Policy(CSP):限制页面只能加载白名单里的脚本和资源,防 XSS。
  3. 空行(CRLF):隔开响应头和响应体。
  4. 响应体(Response Body):真正的网页 HTML、图片字节或 JSON 数据。

注意

HTTP/1.1 默认开启 Connection: keep-alive(长连接),一条 TCP 连接可以连续收发好几次请求;到了 HTTP/2 改成了二进制帧并支持单连接并发多路复用;HTTP/3 则底层改跑在 UDP 的 QUIC 协议上。而 HTTPS 是在 TCP 握手之后加了一层 TLS 加密,把整条 HTTP 报文(包括路径、查询参数、请求头、Cookie 和请求体)全加密成密文再传,防中间人窃听和篡改。

常见 HTTP 方法

不同的 HTTP 方法代表对资源做不同的动作。做接口测试时要注意区分它是不是只读安全(Safe)的,以及是不是幂等(Idempotent,连发好几次跟发一次结果一样)的:

方法用来干什么有请求体吗只读吗幂等吗
GET读页面或查数据无是是
HEAD只拿响应头、不要响应体(常用来探测资源在不在)无是是
OPTIONS问服务器支持哪些请求方法或跨域配置无是是
POST提交数据、触发操作或新增记录(如登录、发帖、加书架)有否否(连发两次可能建出两条重复记录)
PUT完整替换指定位置的数据(如把阅读进度存为第 3 章)有否是(连存三次“第 3 章”,结果还是第 3 章)
DELETE删除指定资源(如删书评、移出书架)通常无否是(删掉之后状态一直是已删除)

常见 HTTP 状态码

三位数字状态码的百位数代表大类,最常打交道的有这几个:

  • 2xx 成功:
    • 200 OK:请求成功,响应体里有返回内容。
    • 201 Created:新建资源成功(常见于 POST)。
    • 204 No Content:执行成功,但没有响应体需要返回(常见于 DELETE)。
  • 3xx 重定向:
    • 301 Moved Permanently / 302 Found:永久或临时跳转到响应头 Location 指向的新地址。
    • 303 See Other:让浏览器改用 GET 方法去请求 Location 新地址,常用于 POST 提交表单成功后的页面跳转。
    • 307 Temporary Redirect:要求跳转时保持原来的请求方法和请求体不变(原来是 POST 跳转后还发 POST)。
    • 304 Not Modified:告诉浏览器本地缓存还没过期,不用重下正文。
  • 4xx 客户端错误:
    • 400 Bad Request:请求参数格式不对或 JSON 写错了。
    • 401 Unauthorized:没登录(没带凭证,或者凭证无效)。
    • 403 Forbidden:没权限(认识你是谁,但不准你访问这个资源)。
    • 404 Not Found:路径或资源不存在。
    • 405 Method Not Allowed:路径存在,但不支持你用的 HTTP 方法(比如只收 POST 的接口你发了 GET)。
    • 415 Unsupported Media Type:请求体格式不对(比如接口要 application/json,你却发了表单格式)。
  • 5xx 服务端错误:
    • 500 Internal Server Error:后端代码崩了(比如未捕获异常、SQL 报错)。
    • 502 Bad Gateway / 504 Gateway Timeout:Nginx 等反向代理连不上后面的应用服务,或者等超时了。

要注意区分HTTP 通信成功和业务结果:比如去搜一本不存在的小说,服务器正常查完库,给你返回了一张写着“没有找到匹配的小说”的网页,这时候 HTTP 状态码照样是 200 OK。

搜索成功了吗

练习

你搜索一个书名,Network 显示 200,响应 HTML 写着“没有找到匹配的小说”。哪项结论得到支持?

A. 网络一定中断了。 B. 搜索操作返回了正常响应,但本次条件没有匹配书目。 C. 状态为 200,所以该小说一定存在。 D. 应改用 DELETE 才能查看搜索结果。

提交选项字母。

提交答案

题解 Hint