HTTP报文(请求报文和响应报文)详解
HTTP 报文是 HTTP 应用程序之间发送的数据块,以一些文本形式的元信息开头,这些信息描述了报文的内容及含义,后面跟着可选的数据部分。
HTTP 报文是面向文本的,报文中的每一个字段都是一些 ASCII 码串,各个字段的长度是不确定的。
报文的组成包括三部分,报文首部、空行和报文主体,如下图所示。

图 1 报文的组成
HTTP 报文包括请求报文和响应报文两类。这些报文在客户端、服务器端和代理之间流动。一次 HTTP 请求,HTTP 报文会从“客户端”流到“代理”再流到“服务器端”,在服务器端完成工作之后,报文又会从“服务器端”流到“代理”再流到“客户端”。
请求报文指浏览器发给服务器端的内容。响应报文指服务器端发回给浏览器的内容。

图 2 请求报文格式
在请求报文中,开始行就是请求行。请求行包括三部分,分别为请求方式、访问路径和 HTTP 版本号。
请求头包含很多内容,如 Content-Type(内容类型)、Content-Length(指定 Body 长度)、User-Agent(用户代理)等。
请求体就是报文的主要数据部分,可以是任意数据类型的数据。比如请求体中包含了要发给服务器端的数据,响应体中装载了要返回给客户端的数据。
请求报文的格式如下。
HTTP 中包括以下 8 种请求方式:
常见的有 GET、POST、PUT、DELETE 等,重点掌握 GET 请求和 POST 请求,其他请求方式这里暂不做介绍。
GET 请求的请求参数拼接在 URL 地址中,请求参数是可见的,因为地址栏数据大小一般限制为 4kB,所以 GET 请求数据大小受限,且只能携带纯文本。由于在请求首行中已经携带请求参数,故无须请求体,也没有请求空行,因此 GET 请求的封装和解析都很快、效率较高。
GET 和 POST 请求的区别如下表所示:
一般情况下,单击超链接或者在网页地址栏直接输入 URL 地址访问服务器端时,默认请求方式均为 GET 请求,而 Form 表单提交可以借助 GET 请求,也可以借助 POST 请求,关键在于 method 属性值:
下面通过具体案例来分别演示 GET 请求和 POST 请求。
修改 admin.html 文件,通过创建一个超链接和一个表单来演示 GET 请求,示例代码如下:

图 3 按F12键查看GET请求的Headers信息
使用不同浏览器查看 F12 页面时,显示形式可能有所不同,图 3 是通过谷歌浏览器查看的结果。如下图所示,在 Edge 浏览器中按 F12 键查看请求和响应信息,导航栏均翻译为中文形式。

图 4 在Edge浏览器中按F12键查看请求和响应信息
下面分别对 GET 请求的各部分展开介绍。请求行的示例代码如下。
请求头(HTTP 请求中的 Headers)的示例代码如下:

图 5 按F12键查看POST请求的Headers信息
下面分别对 POST 请求各个部分展开介绍。请求行的示例代码如下:
请求体即浏览器提交给服务器端的内容,示例代码如下:

图 6 响应报文格式
响应报文格式如下:
version、headers 和 entity-body 在请求报文中已经做过解释,这里不再重复。
响应行的示例代码如下:
响应头的示例代码如下:
响应体即需要浏览器解析使用的内容。如果响应的是 HTML 页面,最终响应体内容会被浏览器显示到页面中,示例代码如下:
比较有代表性的响应码如下:
响应状态码分为很多种,一般以开头第一位数字作为区分,下面将对其详细介绍。
“1xx”形式的响应状态码,表示临时响应并需要请求者继续执行操作的状态代码,如下表所示。
“2xx”形式的响应状态码,表示成功处理了请求的状态代码,如下表所示。
“3xx”形式的响应状态码,表示要完成请求,需要进一步操作。通常情况下,这些状态代码用来重定向,如下表所示。
“4xx”形式的响应状态码,表示请求可能出错,妨碍了服务器端的处理,如下表所示。
“5xx”形式的响应状态码,表示服务器端在尝试处理请求时发生内部错误。值得注意的是,这些错误可能是服务器端本身的错误,而不是请求出错,如下表所示。
HTTP 报文是面向文本的,报文中的每一个字段都是一些 ASCII 码串,各个字段的长度是不确定的。
报文的组成包括三部分,报文首部、空行和报文主体,如下图所示。

图 1 报文的组成
HTTP 报文包括请求报文和响应报文两类。这些报文在客户端、服务器端和代理之间流动。一次 HTTP 请求,HTTP 报文会从“客户端”流到“代理”再流到“服务器端”,在服务器端完成工作之后,报文又会从“服务器端”流到“代理”再流到“客户端”。
请求报文指浏览器发给服务器端的内容。响应报文指服务器端发回给浏览器的内容。
HTTP请求报文
请求报文一般包括四部分,分别为请求行(Request Line)、请求头(Headers)、空行(Blank Line)、请求体(Request Body),如下图所示。
图 2 请求报文格式
在请求报文中,开始行就是请求行。请求行包括三部分,分别为请求方式、访问路径和 HTTP 版本号。
请求头包含很多内容,如 Content-Type(内容类型)、Content-Length(指定 Body 长度)、User-Agent(用户代理)等。
请求体就是报文的主要数据部分,可以是任意数据类型的数据。比如请求体中包含了要发给服务器端的数据,响应体中装载了要返回给客户端的数据。
请求报文的格式如下。
<method> <request-URL> <version> <headers> <entity-body>
- method(方法),即请求方式,客户端希望服务器端对资源执行的动作,比如 GET、POST;
- request-URL(请求路径),命名了所请求的资源;
- version(版本),报文所使用的 HTTP 版本;
- headers(首部),可以有零个或者多个首部,每个首部都包含一个名字,后面跟着一个冒号“:”,然后是一个可选的空格,接着是一个值,最后是一个“CRLF”;
- entity-body(实体的主体部分),包含一个由任意数据组成的数据块。注意,并不是所有的报文都包含实体的主体部分。
HTTP 中包括以下 8 种请求方式:
- HTTP1.0 定义了 GET、POST、HEAD 这 3 种请求方式;
- HTTP1.1 则新增了 OPTIONS、PUT、DELETE、TRACE 和 CONNECT 这 5 种请求方式。
常见的有 GET、POST、PUT、DELETE 等,重点掌握 GET 请求和 POST 请求,其他请求方式这里暂不做介绍。
GET 请求的请求参数拼接在 URL 地址中,请求参数是可见的,因为地址栏数据大小一般限制为 4kB,所以 GET 请求数据大小受限,且只能携带纯文本。由于在请求首行中已经携带请求参数,故无须请求体,也没有请求空行,因此 GET 请求的封装和解析都很快、效率较高。
POST 请求参数在地址栏是不可见的相对安全,请求体数据大小也没有限制,可以用来上传任意内容,例如文件、文本等,且上传文件只能使用 POST 请求来实现。与 GET 请求相比,最大的区别是有请求体,数据在请求体中携带,也因此效率较低。浏览器默认提交的请求均为 GET 请求。
GET 和 POST 请求的区别如下表所示:
GET 请求 | POST 请求 | |
---|---|---|
请求参数位置 | 拼接在地址栏 | 请求体内 |
数据量的大小 | 有限,地址栏数据大小一般限制为 4kB | 理论上是无限的 |
数据安全 | 不安全,地址栏可见 | 相对安全,打开开发者工具(按 F12 键)查看请求体可见 |
请求体 | 没有请求体 | 有请求体 |
一般情况下,单击超链接或者在网页地址栏直接输入 URL 地址访问服务器端时,默认请求方式均为 GET 请求,而 Form 表单提交可以借助 GET 请求,也可以借助 POST 请求,关键在于 method 属性值:
- 如果 method 值为 get,则表单提交的请求方式为 GET 请求;
- 如果 method 值为 post,则表单提交的请求方式为 POST 请求。
下面通过具体案例来分别演示 GET 请求和 POST 请求。
1) GET请求
首先在 JavaWeb 工程下创建 chapter06_http 项目,并复制一份 chapter05_tomcat 项目代码到 chapter06_http 项目下。修改 admin.html 文件,通过创建一个超链接和一个表单来演示 GET 请求,示例代码如下:
<!--超链接--> <a href="https://www.baidu.com/">点我</a><br/><br/> <!--表单提交之 GET 请求--> <form action="login success.html" method="get"> 用户姓名:<input name="username" type="text" /><br/> 用户密码:<input name="password" type="password" /><br/> <input type="submit" value="登录" /> </form>运行代码,按 F12 键或打开浏览器开发者工具,选择“Network”选项,重新刷新页面后单击该页面 admin.html,选择查看“Headers”信息,如下图所示。

图 3 按F12键查看GET请求的Headers信息
使用不同浏览器查看 F12 页面时,显示形式可能有所不同,图 3 是通过谷歌浏览器查看的结果。如下图所示,在 Edge 浏览器中按 F12 键查看请求和响应信息,导航栏均翻译为中文形式。

图 4 在Edge浏览器中按F12键查看请求和响应信息
下面分别对 GET 请求的各部分展开介绍。请求行的示例代码如下。
GET /chapter06 http/login_success.html?username=admin&password=123213 HTTP/1.1从上述代码中可以看出,请求方式为 GET 请求;访问的服务器中的资源路径为“/chapter06_http/login_success.html”;其中,该请求包含两个请求参数 username 和 password,其值分别为 admin 和 123213;遵循的协议的版本为 HTTP1.1。
请求头(HTTP 请求中的 Headers)的示例代码如下:
Host: localhost:8080 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: http://localhost:8080/05_web_tomcat/login.html Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7从上述代码中可以看出,请求头均以 key-value 键值对组成,下面对其内容一一分析:
- Host 代表主机虚拟地址;
- Connection 值为 keep-alive,表示本次连接方式为长连接;
- “Upgrade-Insecure-Requests”表示请求协议的自动升级,比如 HTTP 的请求,服务器端却是 HTTPS 开头,因为浏览器自动会将请求协议升级为 HTTPS;
- User-Agent 表示用户系统信息;
- Accept 表示浏览器支持的文件类型,其中“text/html”表示 HTML 数据格式,“application/xml”表示 XML 数据格式;
- Referer 表示当前页面的上一个页面的路径,即指明当前页面是通过哪个页面跳转过来的,可以通过此路径跳转回上一个页面;
- “Accept-Encoding”表示浏览器支持的压缩格式;
- “Accept-Language”表示浏览器支持的语言;
2) POST请求
POST 请求要求将 Form 标签的 method 属性设置为 post,示例代码如下:<form action="target.html" method="post"> 用户名:<input name="username" type="text" /> 用户密码:<input name="pwd" type="password" /> <input type="submit" value="登录" /> </form>运行代码,按 F12 键或打开浏览器开发者工具,选择“Network”选项,重新刷新页面后单击该页面 admin.html,选择查看“Headers”信息,如下图所示。

图 5 按F12键查看POST请求的Headers信息
下面分别对 POST 请求各个部分展开介绍。请求行的示例代码如下:
POST /chapter06_http/login_success.html HTTP/1.1从上述代码中可以看出,请求方式为 POST 请求;访问服务器端的资源路径“/chapter06_http/login_success.html”,且路径中不包括请求参数的内容,请求参数保存在请求体中;遵循协议的版本为 HTTP1.1。
Host: localhost:8080 Connection: keep-alive Content-Length: 31 Cache-Control: max-age=0 Origin: http://localhost:8080 Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: http://localhost:8080/05_web_tomcat/login.html Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: JSESSIONID-有些内容在 GET 请求中的请求头已经介绍过,这里不再重复:
- Content-Length 表示请求体内容的长度;
- Cache-Control 值为“max-age=0”,表示无缓存;
- Content-Type 表示请求体的内容类型,服务器端会根据该类型解析请求体参数。
请求体即浏览器提交给服务器端的内容,示例代码如下:
username=admin&password=1232131该请求体包含了两个参数:username 和 password,对应 GET 请求中 URL 中的参数,由此再次验证了 GET 请求的请求参数直接拼接在 URL 中,而 POST 请求的请求参数存放在请求体中。
HTTP响应报文
响应报文同样包括四部分,分别为响应首行(Status Line)、响应头(Headers)、空行(Blank Line)、响应体(Response Body),如下图所示。
图 6 响应报文格式
响应报文格式如下:
<version> <status> <reason-pharse> <headers> <entity-body>
- status(状态码)由三位数字组成,描述了请求过程中发生的情况。每个状态码的第一个数字都用于描述状态的一般类别,如请求成功或请求出错等。
- reason-pharse(原因短语)是数字状态码的可读版本。
version、headers 和 entity-body 在请求报文中已经做过解释,这里不再重复。
响应行的示例代码如下:
HTTP/1.1 200 OK从上述代码中可以看出,响应协议为 HTTP1.1,响应状态码为 200,表示请求成功。
响应头的示例代码如下:
Server: Apache-Coyote/1.1 Accept-Ranges: bytes ETag: W/"157-1534126125811" Last-Modified: Mon, 13 Aug 2018 02:08:45 GMT Content-Type: text/html Content-Length: 157 Date: Mon, 13 Aug 2018 02:47:57 GMT下面对其内容进行分析,具体如下:
- Server表示服务器端的版本信息,值为“Apache-Coyote/1.1”;
- Content-Type表示响应体的数据类型,浏览器会根据该类型解析响应体数据;
- Content-Length表示响应体内容的字节数;
- Date表示响应的时间。
响应体即需要浏览器解析使用的内容。如果响应的是 HTML 页面,最终响应体内容会被浏览器显示到页面中,示例代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 恭喜你,登录成功... </body> </html>
HTTP响应状态码
提到响应报文不得不介绍一下响应状态码,响应状态码对浏览器来说很重要,通过它可以对服务器端响应给浏览器的结果一目了然。比较有代表性的响应码如下:
- 200 表示请求成功,浏览器会把响应体内容(通常是 HTML 页面)显示在浏览器中。
- 404 表示请求的资源没有找到,说明客户端错误请求了不存在的资源。
- 500 表示请求资源找到了,但服务器端内部出现了错误。
- 302 表示重定向,当响应码为 302 时,表示服务器端要求浏览器重新再发送一个请求,服务器端会发送一个响应头 Location,用来指定新请求的 URL 地址。
响应状态码分为很多种,一般以开头第一位数字作为区分,下面将对其详细介绍。
“1xx”形式的响应状态码,表示临时响应并需要请求者继续执行操作的状态代码,如下表所示。
响应状态码 | 说明 |
---|---|
100(继续) | 请求者应当继续提出请求。服务器端返回此代码,表示已收到请求的第一部分,正在等待其余部分 |
101(切换协议) | 请求者已要求服务器端切换协议,服务器端已确认并准备切换 |
“2xx”形式的响应状态码,表示成功处理了请求的状态代码,如下表所示。
响应状态码 | 说明 |
---|---|
200(成功) | 服务器端已成功处理了请求。通常,这表示服务器端提供了请求的网页 |
201(已创建) | 请求成功并且服务器端创建了新的资源 |
202(已接受) | 服务器端已接受请求,但尚未处理 |
203(非授权信息) | 服务器端已成功处理了请求,但返回的信息可能来自另一来源 |
204(无内容) | 服务器端成功处理了请求,但没有返回任何内容 |
205(重置内容) | 重置内容。服务器处理成功,用户终端(如浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206(部分内容) | 服务器端成功处理了部分 GET 请求 |
“3xx”形式的响应状态码,表示要完成请求,需要进一步操作。通常情况下,这些状态代码用来重定向,如下表所示。
响应状态码 | 说明 |
---|---|
300(多种选择) | 针对请求,服务器端可执行多种操作。服务器端可根据请求者(user agent)选择一项操作,或提供操作列表供请求者选择 |
301(永久移动) | 请求的网页已永久移动到新位置。服务器端返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置 |
302(临时移动) | 临时移动。与 301 类似,但资源只是临时被移动。客户端应继续使用原 URI |
303(查看其他位置) | 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器端返回此代码 |
304(未修改) | 自从上次请求后,请求的网页未被修改过。服务器端返回此响应时,不会返回网页内容 |
305(使用代理) | 请求者只能使用代理访问请求的网页。如果服务器端返回此响应,那么表示请求者应使用代理 |
307(临时重定向) | 临时重定向。与 302 类似,使用 GET 请求重定向 |
“4xx”形式的响应状态码,表示请求可能出错,妨碍了服务器端的处理,如下表所示。
响应状态码 | 说明 |
---|---|
400(错误请求) | 服务器端不理解请求的语法 |
401(未授权) | 请求要求请求身份验证。对于需要登录的网页,服务器端可能返回此响应 |
403(禁止) | 服务器端拒绝请求 |
404(未找到) | 服务器端找不到请求的网页 |
405(方法禁用) | 禁用请求中指定的方法 |
406(不接受) | 无法使用请求的内容特性响应请求的网页 |
407(需要代理授权) | 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理 |
408(请求超时) | 服务器端等候请求时发生超时 |
409(冲突) | 服务器端在完成请求时发生冲突。服务器端必须在响应中包含有关冲突的信息 |
410(已删除) | 如果请求的资源已被永久删除,服务器端就会返回此响应 |
411(需要有效长度) | 服务器端不接受不含有有效内容长度标头字段的请求 |
412(未满足前提条件) | 服务器端未满足请求者在请求中设置的其中一个前提条件 |
413(请求实体过大) | 服务器端无法处理请求,因为请求实体过大,超出服务器端的处理能力 |
414(请求的 URI 过长) | 请求的 URI(通常为网址)过长,服务器端无法处理 |
415(不支持的媒体类型) | 请求的格式不受请求页面的支持 |
416(请求范围不符合要求) | 如果页面无法提供请求的范围,则服务器端会返回此状态代码 |
417(未满足期望值) | 服务器端未满足“期望”请求标头字段的要求 |
“5xx”形式的响应状态码,表示服务器端在尝试处理请求时发生内部错误。值得注意的是,这些错误可能是服务器端本身的错误,而不是请求出错,如下表所示。
响应状态码 | 说明 |
---|---|
500(服务器端内部错误) | 服务器端遇到错误,无法完成请求 |
501(尚未实施) | 服务器端不具备完成请求的功能。例如,服务器端无法识别请求方法时,可能会返回此代码 |
502(错误网关) | 服务器端作为网关或代理,从上游服务器端收到无效响应 |
503(服务不可用) | 服务器端目前无法使用(由于超载或停机维护),但是通常情况下,这只是暂时状态 |
504(网关超时) | 服务器端作为网关或代理,但是没有及时从上游服务器端收到请求 |
505(HTTP 版本不受支持) | 服务器端不支持请求中所使用的 HTTP 版本 |