首页 > 编程笔记 > Java笔记 阅读:22

HTTP报文(请求报文和响应报文)详解

HTTP 报文是 HTTP 应用程序之间发送的数据块,以一些文本形式的元信息开头,这些信息描述了报文的内容及含义,后面跟着可选的数据部分。

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>

HTTP 中包括以下 8 种请求方式:
常见的有 GET、POST、PUT、DELETE 等,重点掌握 GET 请求和 POST 请求,其他请求方式这里暂不做介绍。

GET 请求的请求参数拼接在 URL 地址中,请求参数是可见的,因为地址栏数据大小一般限制为 4kB,所以 GET 请求数据大小受限,且只能携带纯文本。由于在请求首行中已经携带请求参数,故无须请求体,也没有请求空行,因此 GET 请求的封装和解析都很快、效率较高。

浏览器默认提交的请求均为 GET 请求。

POST 请求参数在地址栏是不可见的相对安全,请求体数据大小也没有限制,可以用来上传任意内容,例如文件、文本等,且上传文件只能使用 POST 请求来实现。与 GET 请求相比,最大的区别是有请求体,数据在请求体中携带,也因此效率较低。

GET 和 POST 请求的区别如下表所示:

表:GET 和 POST 请求的区别
  GET 请求 POST 请求
请求参数位置 拼接在地址栏 请求体内
数据量的大小 有限,地址栏数据大小一般限制为 4kB 理论上是无限的
数据安全 不安全,地址栏可见 相对安全,打开开发者工具(按 F12 键)查看请求体可见
请求体 没有请求体 有请求体

一般情况下,单击超链接或者在网页地址栏直接输入 URL 地址访问服务器端时,默认请求方式均为 GET 请求,而 Form 表单提交可以借助 GET 请求,也可以借助 POST 请求,关键在于 method 属性值:
下面通过具体案例来分别演示 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 键值对组成,下面对其内容一一分析:

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 请求中的请求头已经介绍过,这里不再重复:
请求体即浏览器提交给服务器端的内容,示例代码如下:
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>

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
下面对其内容进行分析,具体如下:
响应体即需要浏览器解析使用的内容。如果响应的是 HTML 页面,最终响应体内容会被浏览器显示到页面中,示例代码如下:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>
    恭喜你,登录成功...
</body>
</html>

HTTP响应状态码

提到响应报文不得不介绍一下响应状态码,响应状态码对浏览器来说很重要,通过它可以对服务器端响应给浏览器的结果一目了然。

比较有代表性的响应码如下:
响应状态码分为很多种,一般以开头第一位数字作为区分,下面将对其详细介绍。

“1xx”形式的响应状态码,表示临时响应并需要请求者继续执行操作的状态代码,如下表所示。

表:“1xx”形式的响应状态码
响应状态码 说明
100(继续) 请求者应当继续提出请求。服务器端返回此代码,表示已收到请求的第一部分,正在等待其余部分
101(切换协议) 请求者已要求服务器端切换协议,服务器端已确认并准备切换

“2xx”形式的响应状态码,表示成功处理了请求的状态代码,如下表所示。

表:“2xx”形式的响应状态码
响应状态码 说明
200(成功) 服务器端已成功处理了请求。通常,这表示服务器端提供了请求的网页
201(已创建) 请求成功并且服务器端创建了新的资源
202(已接受) 服务器端已接受请求,但尚未处理
203(非授权信息) 服务器端已成功处理了请求,但返回的信息可能来自另一来源
204(无内容) 服务器端成功处理了请求,但没有返回任何内容
205(重置内容) 重置内容。服务器处理成功,用户终端(如浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206(部分内容) 服务器端成功处理了部分 GET 请求

“3xx”形式的响应状态码,表示要完成请求,需要进一步操作。通常情况下,这些状态代码用来重定向,如下表所示。

表:“3xx”形式的响应状态码
响应状态码 说明
300(多种选择) 针对请求,服务器端可执行多种操作。服务器端可根据请求者(user agent)选择一项操作,或提供操作列表供请求者选择
301(永久移动) 请求的网页已永久移动到新位置。服务器端返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置
302(临时移动) 临时移动。与 301 类似,但资源只是临时被移动。客户端应继续使用原 URI
303(查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器端返回此代码
304(未修改) 自从上次请求后,请求的网页未被修改过。服务器端返回此响应时,不会返回网页内容
305(使用代理) 请求者只能使用代理访问请求的网页。如果服务器端返回此响应,那么表示请求者应使用代理
307(临时重定向) 临时重定向。与 302 类似,使用 GET 请求重定向

“4xx”形式的响应状态码,表示请求可能出错,妨碍了服务器端的处理,如下表所示。

表:“4xx”形式的响应状态码
响应状态码 说明
400(错误请求) 服务器端不理解请求的语法
401(未授权) 请求要求请求身份验证。对于需要登录的网页,服务器端可能返回此响应
403(禁止) 服务器端拒绝请求
404(未找到) 服务器端找不到请求的网页
405(方法禁用) 禁用请求中指定的方法
406(不接受) 无法使用请求的内容特性响应请求的网页
407(需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理
408(请求超时) 服务器端等候请求时发生超时
409(冲突) 服务器端在完成请求时发生冲突。服务器端必须在响应中包含有关冲突的信息
410(已删除) 如果请求的资源已被永久删除,服务器端就会返回此响应
411(需要有效长度) 服务器端不接受不含有有效内容长度标头字段的请求
412(未满足前提条件) 服务器端未满足请求者在请求中设置的其中一个前提条件
413(请求实体过大) 服务器端无法处理请求,因为请求实体过大,超出服务器端的处理能力
414(请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器端无法处理
415(不支持的媒体类型) 请求的格式不受请求页面的支持
416(请求范围不符合要求) 如果页面无法提供请求的范围,则服务器端会返回此状态代码
417(未满足期望值) 服务器端未满足“期望”请求标头字段的要求

“5xx”形式的响应状态码,表示服务器端在尝试处理请求时发生内部错误。值得注意的是,这些错误可能是服务器端本身的错误,而不是请求出错,如下表所示。

表:“5xx”形式的响应状态码
响应状态码 说明
500(服务器端内部错误) 服务器端遇到错误,无法完成请求
501(尚未实施) 服务器端不具备完成请求的功能。例如,服务器端无法识别请求方法时,可能会返回此代码
502(错误网关) 服务器端作为网关或代理,从上游服务器端收到无效响应
503(服务不可用) 服务器端目前无法使用(由于超载或停机维护),但是通常情况下,这只是暂时状态
504(网关超时) 服务器端作为网关或代理,但是没有及时从上游服务器端收到请求
505(HTTP 版本不受支持) 服务器端不支持请求中所使用的 HTTP 版本

相关文章