细读《图解HTTP》第二章——简单HTTP协议

知识架构

第五部分HTTP请求方法根据现在常用方法做了调整,与原书部分有部分区别

客户端与服务器端之间的通信

HTTP 协议是一种用于客户端和服务器之间的通信的协议。

发送请求资源的一端称为客户端,提供资源响应的一端称为服务器端。

两台计算机之间使用HTTP 协议通信时,在一条通信线路上必定有一端是客户端,另一端则是服务器端。

实际情况,两台计算机作为客户端和服务器端的角色有可能会互换。但就仅从一条通信路线来说,服务器端和客户端的角色是确定的, 而用 HTTP 协议能够明确区分哪端是客户端, 哪端是服务器端。

由请求与响应进行交换达成通信

HTTP 协议规定, 请求从客户端发出, 最后服务器端响应该请求并返回。 换句话说, 肯定是先从客户端开始建立通信的, 服务器端在没有接收到请求之前不会发送响应。

请求报文

响应报文

无状态的协议

HTTP 是一种不保存状态, 即无状态(stateless) 协议HTTP 协议自身不对请求和响应之间的通信状态进行保存。 也就是说在 HTTP 这个级别, 协议对于发送过的请求或响应都不做持久化处理。

使用 HTTP 协议, 每当有新的请求发送时, 就会有对应的新响应产生。 协议本身并不保留之前一切的请求或响应报文的信息。

随着 Web 的不断发展, 因无状态而导致业务处理变得棘手的情况增多了。 比如,用户登录到一家购物网站, 即使他跳转到该站的其他页面后,也需要能继续保持登录状态。针对这个实例网,站为了能够掌握是谁送出的请求, 需要保存用户的状态。于是引入了 Cookie 技术。 有了 Cookie 再用 HTTP 协议通信, 就可以管理状态了。

请求URI定位资源

HTTP 协议使用 URI 定位互联网上的资源。正是因为 URI 的特定功能,在互联网上任意位置的资源都能访问到。

当客户端请求访问资源而发送请求时,在请求报文中的指定请求 URI。指定请求 URI 的方式有很多。

URI为完整的请求URI

GET HTTP/1.1

在首部字段Host中写明网络域名或IP地址

GET /index.htm HTTP/1.1

Host:www.tizhenkeji.com

除此之外, 如果不是访问特定资源而是对服务器本身发起请求,可以用一个 * 来代替请求URI。下面这个例子是查询 HTTP 服务器端支持的 HTTP 方法种类。

OPTIONS * HTTP/1.1

HTTP请求方法

要了解HTTP请求方法,我们可借助抓包工具Httpwatch,来加深了解。Httpwatch是一个专门用来抓取web报文的浏览器抓包插件。

HTTP 请求可以使用多种请求方法。常用的主要为GET、POST,一般使用的还包括:HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

GET:获取资源

请求指定的页面信息,并返回实体主体。我们平常通过浏览器登陆网站时,大部分的请求都是使用GET方法,比如我们在浏览器输入栏输入访问百度首页。整个访问过程通过HTTPWATCH抓包发现,整个过程包括12个请求,都采用GET方法。

也就是说,GET方法更多的是在客户端申请提出访问服务器资源的请求,所以我们在通过浏览器浏览网站时候,大部分的行为都是希望访问服务器的某些资源,这也就是为什么几乎所有请求都是GET方法。如下图,客户端表示我想访问服务器的某个资源,通过GET方法来请求。

POST:传输实体主体

POST 的主要目的并不是获取响应的主体内容,而是向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。如下图所示,客户端表示,我要给服务器提交表单,或者上传文件的请求,此时常采用POST方法。

采用POST请求时,数据被包含在请求体中。如我们访问百度首页后,我们需要登陆自己注册的百度账号,在输入用户名、密码后,点击登陆按钮就是一个POST请求,输入验证码,提交验证码也是一个POST请求,下图就是在登陆过程中,一个提交登陆,一个提交验证码的两个POST请求。

POST请求会导致新的资源的建立和/或已有资源的修改,如我们登陆成功百度后,页面会重新建立许多GET请求,浏览器页面会显示许多新的资源。

登陆前是下图页面。

在最后提交验证码,登陆成功后是下图页面。

资源重新建立后,页面显示如下。

PUT:传输文件

PUT方法用来传输文件。 就像 FTP 协议的文件上传一样, 要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置。但是,鉴于 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件,存在安全性问题,因此一般的 Web 网站不使用该方法

HEAD 获得报文首部

类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头。用于确认URI 的有效性及资源更新的日期时间等。

DELETE

DELETE 方法用来删除文件,请求服务器删除指定的页面, 是与 PUT 相反的方法。 DELETE 方法按请求 URI 删除指定的资源。但是, HTTP/1.1 的 DELETE 方法本身和 PUT 方法一样不带验证机制, 所以一般的 Web 网站也不使用 DELETE 方法

TRACE

追踪路径 ,回显服务器收到的请求,主要用于测试或诊断。

CONNECT

要求用隧道协议连接代理,HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。

PATCH

是对 PUT 方法的补充,用来对已知资源进行局部更新 。

OPTIONS

询问支持的方法,允许客户端查看服务器的性能。

为节省通信量而推出的持久链接

HTTP 协议的初始版本中, 每进行一次 HTTP 通信就要断开一次 TCP连接。

以当年的通信情况来说, 因为都是些容量很小的文本传输, 所以即使这样也没有多大问题。 可随着 HTTP 的普及, 文档中包含大量图片的情况多了起来。 比如,使用浏览器浏览一个包含多张图片的 HTML页面时, 在发送请求访问 HTML页面资源的同时, 也会请求该 HTML页面里包含的其他资源。 因此, 每次的请求都会造成无谓的 TCP 连接建立和断开, 增加通信量的开销。

为解决上述TCP 连接的问题, HTTP/1.1 和一部分的 HTTP/1.0 想出了持久连接(HTTP Persistent Connections, 也称为 HTTP keep-alive 或HTTP connection reuse) 的方法。 持久连接的特点是, 只要任意一端没有明确提出断开连接, 则保持 TCP 连接状态。

持久连接旨在建立 1 次 TCP 连接后进行多次请求和响应的交互持久连接的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。 另外, 减少开销的那部分时间,使HTTP请求和响应能够更早地结束, 这样 Web 页面的显示速度也就相应提高了。

在HTTP/1.1 中,所有的连接默认都是持久连接, 但在 HTTP/1.0 内并未标准化。 虽然有一部分服务器通过非标准的手段实现了持久连接,但服务器端不一定能够支持持久连接。 毫无疑问, 除了服务器端, 客户端也需要支持持久连接。持久连接使得多数请求以管线化(pipelining) 方式发送成为可能。 从前发送请求后需等待并收到响应, 才能发送下一个请求。 管线化技术出现后, 不用等待响应亦可直接发送下一个请求。这样就能够做到同时并行发送多个请求, 而不需要一个接一个地等待响应了。

比如,当请求一个包含 10 张图片的 HTML Web 页面, 与挨个连接相比,用持久连接可以让请求更快结束。 而管线化技术则比持久连接还要快。请求数越多,时间差就越明显。

使用cookie状态管理

HTTP 是无状态协议, 它不对之前发生过的请求和响应的状态进行管理。 也就是说, 无法根据之前的状态进行本次的请求处理。假设要求登录认证的 Web 页面本身无法进行状态的管理(不记录已登录的状态) , 那么每次跳转新页面不是要再次登录, 就是要在每次请求报文中附加参数来管理登录状态。

不可否认, 无状态协议当然也有它的优点。 由于不必保存状态, 自然可减少服务器的 CPU 及内存资源的消耗。 从另一侧面来说, 也正是因为 HTTP 协议本身是非常简单的, 所以才会被应用在各种场景里。

图: 如果让服务器管理全部客户端状态则会成为负担

保留无状态协议这个特征的同时又要解决类似的矛盾问题, 于是引入了 Cookie 技术。 Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息, 通知客户端保存 Cookie。 当下次客户端再往该服务器发送请求时, 客户端会自动在请求报文中加入 Cookie 值后发送出去。

服务器端发现客户端发送过来的 Cookie 后, 会去检查究竟是从哪一个客户端发来的连接请求, 然后对比服务器上的记录, 最后得到之前的状态信息。

没有 Cookie 信息状态下的请求

第 2 次以后(存有 Cookie 信息状态) 的请求

上图展示了发生 Cookie 交互的情景, HTTP 请求报文和响应报文的内容如下。1. 请求报文(没有 Cookie 信息的状态)2. 响应报文(服务器端生成 Cookie 信息)3. 请求报文(自动发送保存着的 Cookie 信息)