主题
请求与响应报文
本页对应 1-2请求与响应报文,共 3 段视频,约 22 分钟。
学习目标
- 能说出 HTTP 请求报文的四个组成部分(请求行、请求头、空行、请求体),并说明每一部分的作用与排列顺序。
- 能识别请求行中的请求方法、URL 和协议版本,并解释请求头中
Content-Type的含义(告知服务器提交数据的格式)。 - 能在 Chrome 开发者工具的“网络”面板中定位 Ajax 请求,通过“标头 / 载荷(Payload)”查看请求头与请求体,并通过“查看源代码”查看原始报文。
- 能借助请求报文中的载荷数据反推前端错误位置:先确认提交给服务器的数据是否正确,再回溯到数据获取与赋值代码,定位并修复选择器错误。
- 能说出响应报文的四个组成部分(响应行/状态行、响应头、空行、响应体),并在浏览器中查看响应标头、响应体与格式化预览数据。
- 能解释常见 HTTP 响应状态码的分类(2xx 成功、4xx 客户端错误),并说明 404 的含义及“URL 写错”这一典型排查方向。
知识点
从“格式约定”理解请求报文
为什么需要:浏览器和服务器要通信,不能各发各的。HTTP 协议规定了浏览器发送内容、服务器返回内容的格式。浏览器按照 HTTP 协议要求发给服务器的内容,就叫“请求报文”。服务器收到符合格式的请求报文后,才知道浏览器要做什么。
怎么想:先别急着记四个部分,先抓住一个核心——请求报文是“按协议组织起来的一段文本”。服务器会从上往下解析:第一行先判断请求方法,再找 URL,再看协议;后面按“键值对”读附加信息;遇到空行后,才把后面的内容当作提交给服务器的数据。
怎么做:以注册用户为例,浏览器发起请求后,服务器收到的请求报文格式如笔记图所示:

从图中可以看到,请求报文由四部分组成:请求行、请求头、空行、请求体。
易错点:不要以为请求报文里所有内容都是手写的。请求行中的请求方法、URL 来自代码设置,例如请求方法在 method 中设置,URL 在 action 一类属性中设置;而请求头中很多内容由浏览器自动生成。目前需要重点关注 Content-Type,它告诉服务器本次提交的数据是什么格式。
请求报文的四个组成部分
为什么需要:把请求报文拆成四部分,是为了知道服务器“按什么顺序、按什么含义”读取内容。否则看到一大段文本,就不知道哪一行是地址、哪一段是数据。
怎么想:按从上到下的顺序记:第一行是请求行;第二行到空行前是请求头;空行是分隔符;空行后面是请求体。
怎么做:
- 请求行:包含请求方法、URL、协议。服务器先看到
POST,就知道浏览器要提交数据;再看到 URL,就知道要找哪个资源;最后看到协议,就知道内容符合 HTTP 要求。 - 请求头:以“键: 值”的格式携带附加信息。比如
Content-Type指定本次传递的内容类型。转写稿中特别强调,注册案例里提交的是 JSON 格式数据,服务器看到Content-Type后就知道按 JSON 来理解。 - 空行:分割请求头。服务器看到空行,就知道上面的头部信息告一段落,下面的内容是浏览器提交给服务器的数据。
- 请求体:发送给服务器的资源或数据。注册案例中,请求体里就是用户名、密码等 JSON 数据。
易错点:请求头和请求体不要混。请求头是“说明信息”,请求体是“真正提交的数据”。空行不是可有可无的装饰,它是服务器解析时的分界点。
在 Chrome 中查看请求报文
为什么需要:只背组成不够,实际开发中要能打开浏览器确认“到底发出去了什么”。这是排查前后端通信问题的基本技能。
怎么想:请求报文是浏览器发出去的,所以要到 Chrome 开发者工具的“网络”面板看。因为案例是 AJAX 请求,所以分类选 Fetch/XHR,再点击具体请求。
怎么做:按转写稿步骤:F12 打开开发者工具 → 进入“网络”面板 → 切换到 Fetch/XHR → 触发请求(例如点击注册或登录按钮)→ 点击出现的请求 → 在“标头”里找“请求标头”。在这里能看到键值对形式的请求头。若要看请求方法、URL、协议,点击“查看源代码”,请求行就会出现。转写稿提到,Chrome 处理后的 URL 可能显示得短一些,这是浏览器处理后的结果。
查看请求体时,到“载荷”(英文界面为 Payload)界面。这里能看到提交给服务器的数据。笔记图展示了查看请求体的位置:

易错点:转写稿中“再核”是“载荷”的同音误写,实际应找“载荷/Payload”。另外,载荷里有时显示的是格式化后的对象,不一定是原始 JSON 字符串;要看原始格式,可点“查看源代码”。空行在 Chrome 处理后的界面里通常看不到,不要因为界面上没有空行就以为请求报文没有空行。
用请求报文辅助定位错误
为什么需要:实际开发中,登录失败、注册失败不一定先靠通读代码解决。先看请求报文,可以快速判断“提交给服务器的数据对不对”。
怎么想:如果页面提示用户名或密码错误,先怀疑提交数据是否有问题。到网络面板看请求的“载荷”:用户名是什么、密码是什么。若载荷里的密码值明显不对,就顺着“哪里给请求参数赋值”往回找。
怎么做:转写稿案例中,输入正确用户名和密码仍登录失败。打开网络面板,点击登录请求,在“载荷”里发现密码字段的值竟然是用户名,而不是输入的密码。回到代码,先找到登录按钮点击事件中的 XHR 请求和 data,发现变量名没问题;继续往上找变量声明和赋值,发现第二个选择器写成了用户名选择器,应该用密码框的选择器。改正选择器后,登录成功。
易错点:不要一上来通读全部代码。请求报文的作用是帮你把范围缩小到“提交数据”和“取数据”的关键位置。变量名对,不代表变量值对;真正要确认的是请求载荷里的值。
小结
浏览器发送给服务器的内容叫请求报文,需要符合 HTTP 协议要求。请求报文由请求行、请求头、空行、请求体四部分组成。请求行包含请求方法、URL、协议;请求头以键值对携带附加信息,目前重点了解 Content-Type;空行分隔请求头;请求体是发送给服务器的资源或数据。Chrome 中通过“网络 → Fetch/XHR → 具体请求 → 标头/请求标头”查看请求行和请求头,通过“载荷/Payload”查看请求体,必要时点“查看源代码”看原始格式。掌握这些,既能理解协议格式,也能在调试时快速定位提交数据的问题。
本节目标:用请求报文定位错误
上一节我们学会了在 Chrome 开发者工具里查看请求报文。本节要解决的是:学会查看请求报文之后,它对实际开发有什么用?
答案很直接:它可以帮我们确认代码发送给服务器的数据是否真的正确,从而快速定位错误。尤其在前后端联调时,页面提示“用户名或密码错误”,不一定是服务器坏了,也不一定是用户输错了,很可能是前端提交的请求体数据有问题。
为什么先看请求报文,而不是先读代码
同桌小花已经写完了登录功能,但输入已注册的用户名和密码后始终登录不了,页面提示用户名或密码错误。按照以前的思路,可能一上来就从头阅读代码。但代码一多,阅读成本很高,而且容易迷路。
更高效的思路是:先确认浏览器实际发给服务器的数据是什么。请求报文是代码运行后的结果,请求体里就带着登录提交的用户名和密码。只要把请求体里的值和用户输入的值对比,就能判断问题出在“提交数据”还是“服务器校验”。这比逐行读代码更快。
复现问题:先确认输入没有错
先别急着改代码。打开页面,输入用户名 IT黑马001,密码 123456。为了确认密码框里确实输入正确,可以右键审查元素,把密码框的 type 临时改成 text,看到明文是 123456,说明输入没有问题。然后点击登录,确实仍然登录失败。
此时不要猜,直接打开开发者工具:按 F12,进入 Network(网络)面板,筛选 XHR/AJAX 请求,点击登录按钮后出现登录请求。点开该请求,在 Payload(载荷,转写中说的“再合”就是它)里查看提交给服务器的数据。
从请求体反推代码位置
在 Payload 中看到:用户名是 IT黑马001,密码却也成了 IT黑马001,而期望密码应是 123456。说明请求体数据错了,怪不得登录不上。
接下来反推:什么时候发的请求?点击登录按钮时。所以先找登录按钮的点击事件。进入对应代码后,找到发起请求的函数,查看提交数据 data 里的变量名,发现 password 这个变量名没有写错。变量名对,不代表值对,于是继续往上找变量的声明和赋值位置。结果发现:第二个选择器本应取密码框,却写成了 username。这就是错误根源。
回到页面右键审查密码框,确认正确的类名是 password,复制后替换代码中的错误选择器,保存并重新登录,问题解决。
易错点
第一,不要一上来通读全部代码,应先看请求体数据,再定位到发请求和取值的代码。第二,Payload 里看到的是格式化后的对象,想看原始 JSON 可点“查看源代码”。第三,变量名写对不代表变量值对,要继续追到赋值处。第四,选择器类名要以前端页面审查结果为准,不能凭感觉写。第五,改完要保存、刷新并重新发请求验证。
小结
查看请求报文的核心价值是:快速确认我们发送的内容是否正确。排查顺序可以记为:复现问题 → 看 Network 中的请求 → 看 Payload 请求体 → 对比期望值 → 找到发请求的位置 → 往上追变量赋值 → 修正后复测。这样不需要阅读所有代码,只找关键位置,能明显缩短调试时间。
答案
- 可以快速确认我们发送的内容是否正确
响应报文是什么,为什么需要先看格式
HTTP 协议规定了浏览器发送内容和服务器返回内容的格式。浏览器按协议格式发给服务器的内容叫请求报文;服务器按协议格式返回给浏览器的内容叫响应报文。浏览器收到符合格式的响应报文后,才能知道这次请求是成功还是失败,以及服务器返回的是什么资源。
为什么需要:前后端通信不是“随便返回一段文字”,而是按固定结构交换信息。只有结构固定,浏览器和开发者工具才能正确解析状态、内容类型和响应数据。
怎么想:把响应报文看成一封格式固定的信:第一行先说明结果,中间是附加说明,空行后才是正文。
怎么做:阅读响应报文时从上往下看,先看响应行判断结果,再看响应头了解内容类型,最后看响应体。
易错点:不要一上来只盯响应体;响应头和状态码往往先告诉你“这次请求有没有成功、返回的是什么格式”。

响应报文的四个组成部分
响应报文和请求报文格式很相似,也由四部分组成:响应行、响应头、空行、响应体。
响应行(状态行):包含协议、HTTP 响应状态码、状态信息。课程示例中,浏览器看到状态码和状态信息,就能知道请求成功还是失败。
- 为什么需要:让浏览器第一眼判断本次请求结果。
- 怎么想:第一行是“结论行”,重点看状态码。
- 怎么做:从第一行中识别协议、数字状态码和后面的状态文本。
- 易错点:状态行也叫响应行;不要只记名字,要知道它承载“成功/失败”的判断信息。
响应头:以键值对格式携带附加信息,例如
Content-Type告诉浏览器本次返回内容的类型。课程中示例返回 JSON,因此响应头里会出现与 JSON 对应的内容类型。- 为什么需要:浏览器需要知道“返回的是什么类型的数据”,才能按相应方式处理。
- 怎么想:响应头是“附加说明书”,目前重点先掌握
Content-Type。 - 怎么做:在响应头中找键值对,关注
Content-Type的值。 - 易错点:
Content-Type是提示内容类型,不等于响应体本身;其他响应头用到时再查,不必一次全背。
空行:分隔响应头和响应体。
- 为什么需要:没有分隔,解析器无法准确判断“说明部分”到哪里结束、“正文”从哪里开始。
- 怎么想:空行是分界线,空行之后才是服务器返回的资源或数据。
- 怎么做:阅读原始报文时,看到空行就转入响应体。
- 易错点:Chrome 开发者工具通常会帮我们处理报文,空行往往看不到,不能因此认为它不存在。
响应体:服务器返回的资源或数据。课程示例中响应体是 JSON 格式数据,两边是大括号,键用双引号包裹,冒号后是值。
- 为什么需要:真正业务数据通常在这里。
- 怎么想:先由状态码判断结果,再由响应体读取数据。
- 怎么做:在开发者工具中查看 Response;需要格式化查看时看 Preview。
- 易错点:响应体不一定是 JSON,也可能是 HTML、图片等;要看
Content-Type和实际内容。
HTTP 响应状态码:先判断请求结果
HTTP 响应状态码用来表明请求是否成功完成。课程中说明状态码是三位数字,从 1xx 到 5xx;目前重点记住:2xx 表示成功,4xx 表示客户端错误。前端开发中,客户端通常可理解为浏览器这一侧。
为什么需要:状态码让浏览器和开发者快速判断结果,不用先解析完整响应体。
怎么想:先看数字大类,再看具体含义。比如 404 表示服务器找不到资源。
怎么做:在响应行中看状态码;课程用把 URL 故意写错的方式演示 404,随后在 Network 面板查看响应报文。
易错点:看到 404 不要先怀疑服务器“坏了”,更常见的是 URL 写错或资源路径不对;课程中错误 URL 返回 404,响应体里的提示也与“资源找不到”对应。

在 Chrome 中查看响应报文
为什么需要:调试时只看页面提示不够,必须确认服务器实际返回了什么。
怎么想:响应报文属于网络通信结果,应到 Network(网络)面板抓请求,再看对应请求的响应信息。
怎么做:打开开发者工具,进入 Network 面板;当前课程查看的是 XHR 请求,所以切换到 XHR 分类;点击目标请求;在 Headers 中查看响应标头,点击 View source 可看到状态行等原始信息;查看响应体可点 Response,查看格式化后的数据可点 Preview。
易错点:Chrome 会格式化显示,空行通常看不到;Response 里可能是格式化后的对象,想确认原始数据格式可用 View source;中文界面“载荷”对应英文 Payload,“响应”对应 Response,“预览”对应 Preview。
用响应报文辅助调试的思路
课程先用重复注册演示了错误响应报文,又用错误 URL 演示 404。调试时不要急着通读全部代码,而应先确认通信数据:请求有没有发对、服务器响应是什么。若状态码是 404,就优先检查 URL;若响应体提示资源找不到,就与 404 对照。类似地,课程在请求报文调试中通过 Payload 发现提交数据错误,再反推变量赋值和选择器问题。核心是:从报文中的关键数据反推错误位置,缩短定位时间。
易错点:不要把开发者工具格式化后的展示当成原始报文;不要只凭页面提示猜错误,要回到 Network 中看状态码、响应头和响应体。
课件图示





代码示例
代码示例 1:发起注册请求,观察请求报文
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>注册用户 - 请求报文</title>
</head>
<body>
<button class="btn-register">注册用户</button>
<!-- 引入 axios -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 接口地址:换成提供的服务器地址即可
const BASE_URL = '/api'
document.querySelector('.btn-register').addEventListener('click', async () => {
// 要提交给服务器的数据(请求体)
const data = {
username: 'itheima001',
password: '123456'
}
const res = await axios({
url: BASE_URL + '/register', // → 请求行里的 URL
method: 'post', // → 请求行里的请求方法
data: data // → 请求体,axios 自动带上 Content-Type: application/json
})
console.log(res.data)
})
</script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
关键行与易错点
method: 'post'对应请求行第一个单词POST;url对应请求行第二个部分。这两项写在配置对象里,最终会出现在请求行,而不是请求体。data是请求体,axios 传入对象时会自动序列化成 JSON,并自动加上请求头Content-Type: application/json;这一段请求头内容是自动生成的,不用手写。- 易错点:不要再写
JSON.stringify(data),否则请求体变成“字符串的字符串”,服务器解析不出 JSON。 - 查看方式:F12 → 网络(Network) → 选 Fetch/XHR 分栏 → 点击按钮后再点出现的请求 → 标头(Headers)→ 请求标头,点“查看源代码”才看得到请求行;请求体在 载荷(Payload),点“查看源代码”看原始 JSON 字符串。空行被浏览器处理掉了,面板里看不到。
代码示例 2:登录请求体数据错误 —— 用请求报文定位问题
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>登录 - 用请求报文排错</title>
</head>
<body>
<input type="text" class="username" placeholder="用户名" />
<input type="text" class="password" placeholder="密码" />
<button class="btn-login">登录</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
document.querySelector('.btn-login').addEventListener('click', async () => {
// ❌ 错误写法:密码框也用了 .username,导致提交的 password 是用户名的值
// const username = document.querySelector('.username').value
// const password = document.querySelector('.username').value
// ✅ 正确写法:密码框的类名是 .password
const username = document.querySelector('.username').value
const password = document.querySelector('.password').value
const res = await axios({
url: '/api/login',
method: 'post',
data: { username, password } // 请求体
})
console.log(res.data)
})
</script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
关键行与易错点
- 排错顺序:先在页面输入正确账号密码 → 登录失败 → F12 网络 → 点请求 → 载荷,发现
password的值和username一模一样,说明“提交给服务器的数据”错了。 - 由数据反推代码:点击登录按钮才发请求 → 打开按钮点击事件 → 找到
axios的data→ 变量名没问题 → 往上找变量声明,发现第二个querySelector选择器写错。 - 易错点:Bootstrap 输入框上通常还有
form-control类,不要拿它当选择器(两个框都有),要用.username/.password。类名可以去页面右键“审查元素”里复制确认。 - 整个过程不需要通读全部代码,只顺着“请求报文里的数据”反推关键位置,这是实际开发中非常重要的调试技能。
代码示例 3:URL 写错 → 观察 404 响应报文
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>响应报文 - 404 演示</title>
</head>
<body>
<button class="btn-register">注册用户</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
document.querySelector('.btn-register').addEventListener('click', () => {
axios({
// 故意在 URL 后面多写一段,服务器找不到这个资源
url: '/api/register/xxx',
method: 'post',
data: { username: 'itheima001', password: '123456' }
})
.then((res) => {
console.log(res.data)
})
.catch((err) => {
console.log(err)
})
})
</script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
关键行与易错点
- 响应报文同样是四部分:响应行(状态行:协议 + 状态码 + 状态信息)、响应头、空行、响应体。状态码
2xx表示成功,4xx表示客户端(浏览器)错误。 - 查看方式:F12 网络 → 点请求 → 标头 里的 响应标头 看响应头;点“查看源代码”看响应行里的
404;响应体在 响应(Response),格式化后的数据在 预览(Preview)。 404= 服务器找不到资源,最常见原因就是 URL 写错,看到 404 先去检查url这一行。- 易错点:
.then里只处理成功(2xx),4xx 会走.catch,所以别只在.then里打日志,否则“看起来什么都没发生”。真正的排查依据仍以网络面板里的响应报文为准。
常见错误
打开网络面板一片空白,怀疑请求根本没发出去
- 现象:切到 Network 后列表为空,但页面明明有交互。
- 原因:面板是在请求发出之后才打开的,Chrome 只记录打开之后的请求;或过滤条件停在非 Fetch/XHR 分类上。
- 修法:先开 F12 再触发操作;勾选 Preserve log 防止页面跳转清空记录;过滤切到 Fetch/XHR。
在「请求标头」里找不到请求方法、URL 和协议
- 现象:只看到一堆 key: value,第一行不见了。
- 原因:DevTools 默认展示解析后的视图,把请求行拆散隐藏了。
- 修法:点该区域的 view source(查看源代码)切到原始报文视图。
找不到空行,以为报文格式不对
- 现象:请求头与请求体之间看不到分隔行。
- 原因:浏览器渲染时把空行吃掉了。
- 修法:用 view source、右键 Copy as cURL,或改用抓包工具看原始文本。
Payload 里显示的是对象而不是 JSON 字符串,误判“数据格式错了”
- 现象:代码里传的是字符串,面板里却是可折叠对象,于是回头乱改代码。
- 原因:DevTools 对 JSON 做了格式化展示。
- 修法:点 view source 看原始文本,确认双引号、转义、字段名是否真的符合预期。
提交失败就从头逐行读代码
- 现象:几百行代码看半天,找不到问题。
- 原因:没有先确认“发出去的数据到底对不对”。
- 修法:先看 Payload 里提交的值 → 不对就找发起请求的那段(按钮点击事件里的 xhr/fetch)→ 顺着 data 里的变量往上看声明和赋值 → 定位到取值处(高发点是选择器写错)。
看到 404 就断定后端接口挂了
- 现象:状态码 404,直接去质问后端。
- 原因:URL 路径拼错、多了或少了斜杠、参数误写进路径。
- 修法:对照接口文档逐字符核对 URL,先确认是路径错还是资源真不存在。
状态码 200 就认为业务成功
- 现象:状态码 200,页面却提示“用户名或密码错误”。
- 原因:HTTP 状态码只说明这次传输完成,业务结果在响应体里。
- 修法:看 Response / Preview 里的业务字段(如 message、code)。
练习
- 打开任意含 Ajax 的页面,用 Network 找到该请求,分别记录:请求行(view source 视图)、Content-Type 的值、原始请求体,并说明三者各自对应报文的哪一部分。
- 故意把请求 URL 末尾追加一串字符,观察状态码与 Preview 中的 message,写出你从“看到现象”到“得出结论”的完整判断流程。
- 给定一个“登录失败”的场景,只允许看 Network 面板、不许读代码,写出你定位错误的三个步骤,并说明每一步在排除什么可能。
- 对比同一个请求的 Payload 视图与 view source 视图,解释差异原因;再回答:如果后端说“没收到 password 字段”,你第一眼先看哪里?
- 用 Copy as cURL 复制该请求到文本编辑器,手工标出四个组成部分(含空行),并指出哪一部分是 DevTools 里看不到的。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | HTTP协议-请求报文 | 08:53 |
| 2 | 请求报文-辅助调试 | 05:53 |
| 3 | HTTP协议-响应报文 | 07:45 |
小结
- 报文是“证据”而不是“知识”:出问题的第一动作是打开 Network 看真实发出的内容,而不是读代码。
- 请求行、状态行、空行在 DevTools 里默认不可见;凡是要看原始格式,一律走 view source 或 Copy as cURL。
- Content-Type 是唯一必须看的头,它决定服务端和浏览器怎么解析后面的 body;格式对不上,body 再对也白搭。
- 排查顺序固定为:先看数据(Payload / Response)→ 再看发起请求的位置 → 再看数据来源(变量声明与赋值)。这条链路能把排查范围从整个文件缩到几行。
- HTTP 状态码只回答“这次请求成没成”,业务成没成看响应体;遇到 4xx 先怀疑自己的 URL 和参数,别先怀疑后端。
- 前端取值类 bug 的高发点是选择器:Payload 里出现“密码变成了用户名”这类张冠李戴,几乎都是复制粘贴后忘了改选择器。
- 养成“先开面板再操作”的习惯并常开 Preserve log,否则请求会被页面跳转清空,白忙一场。
- 密码框看不到值不代表没输入——必要时临时改 type 或读 value 自证,别把时间浪费在“我肯定输对了”上。