请求报文以 HTTP 方法开头,随后是路径和要使用的HTTP 协议版本,这三部分称为请求行。
我们知道,http请求报文的请求行中,方法是一个动词,比如GET,HEAD,POST,OPTION等等。 如果客户端想要查看 logo.png (一张图片)上次修改的时间,该用什么动词呢? 我们知道 Last-Modified 报头具有该信息,因为客户端对文件实际内容不感兴趣,所以这里适合使用 HEAD 请求。 如果客户端发送表单数据适合用什么动词呢? 表单只能使用两种方法GET和POST,因为我们是要发送数据,所以需要使用POST方法。 如果客户端向服务器请求某个文件比如main.css呢? 每当你需要获取文件内容时,就需要使用GET。所有动词都使用响应体来执行某个操作,或者什么也不执行。 如果客户端想要知道服务器到底支持哪些动词应该怎么办呢? 了解服务器支持哪些动词,正是OPTION方法的目的,所以应该用OPTION。 如果客户端要求服务器向其发送http://google.com的登录页面,应该用什么动词? 和上面一样,这里我们要取回内容,因此唯一合理的方法是GET.
HEAD 方法是一个有趣的方法,因为通过它可以获取文件的所有报头,而不需要接收整个文件本身,这样可以检查存储响应的空间是否充足或者检查该网页的缓存版本是否依然是最新版本。这样的话,如果浏览器在缓存中依然有该文件的最新版本,就不需要重新下载该文件。当你访问网站时,可能不会看到任何HEAD请求,使用 HEAD 验证缓存存在的问题是工作量翻了一番。你发送了 HEAD 请求,然后可能立即发送了 GET 请求,每个请求响应对都被称为一次往返,需要很长时间才能完成。现在的网站有大量资源,在潜在的 GET 请求之前发送 HEAD 请求将大幅降低网站的加载速度,我们可以采取一些方法来降低这些往返操作的成本。稍后将详细讲解,暂时只需记住我们要尽量减少网站的往返操作,也就是尽量减少请求数量。
可以看出,有多种发送请求的方式,要使服务器正确地做出响应,就必须使用正确的动词。
Content-Length是必须包含在每个响应报文中的响应头字段,它告诉浏览器响应中正文的大小。这样浏览器就知道在请求头之后可以接收多少字节,并且在下载文件时可以显示有意义的进度条。
Content-Type是一个可选字段,它告诉您文档的类型。这样浏览器就知道要启动哪个解析引擎。如果是image/ jpeg,则显示图像。如果是text / html,解析它并发出必要的额外HTTP请求等等。
RESTful API 遵循一种叫做 REST 的设计模式,专门用于 HTTP,REST 是Representational State Transfer(表现层状态转化)的简称。光听名称,并不明白是什么意思,并非所有的 API 都遵守 REST 模式,但是有很多都遵守。我们来看看这一概念,基本实体是集合以及位于这些集合中的对象,从集合中获取项目的一般模式是使用 GET 请求加上集合名称和集合中的单个条目的名称。例如,如果我想查询 Richard,我将发送此请求,服务器将获取包含 Richard 的数据的记录。如果我想更新该记录中的数据,我将使用 PUT 请求,并将更新的信息添加到该请求中,每个后续的 GET 请求现在应该生成更新后的记录。POST 请求与 PUT 非常相似,但是你使用它创建新的记录而不是更新现有的记录。注意,你通常不会提供新记录的名称,而是由服务器来设定,该 POST 请求的响应通常会重定向到新创建的记录。DELETE 它会从集合中删除条目。
当我们输入网址,从在地址栏中按下 Enter 键到显示网页之间超过 50% 的时间都花在等待答案上,这段等待时间称为传送首字节的时间,简称 TTFB。如果此网站需要获取其他资源,我们必须等到第一个请求被响应,然后才能发送第二个请求,意味着又要等待一段时间,这段时间没有获得有效利用,这种问题称为队头阻塞。
什么是队头阻塞以及对用户体验有何不良影响? 对于 HTTP 来说,连接就像一个队列,当第一个请求正在被处理时,所有其他请求都需要等待,这样就浪费了很多时间。为了稍微避免这种限制,浏览器打开了六个并行连接,当第一个连接正在等待第一个字节时,第二个请求已经可以发送给第二个连接,以此类推。在浏览器中 打开所有这些连接代价也很高,因为需要进行TCP握手。开启新连接的代价尤其高昂,因为 TCP 握手要确保两台机器都发现新创建的通信渠道,这需要两次往返通信。如果使用的是 HTTPS还需要执行额外的 TLS 握手,完成所有这些操作后,真正的 HTTP 协议才最终接手任务。 浏览器建立六个并行连接,只是暂时解决了队头阻塞问题,如果你的网页上有大量资源,你将花费大量时间去等待,队头阻塞是一个严重的网站性能瓶颈,浏览器打开六个并行连接有所帮助,但是效果不明显。
每次浏览器连接到服务器以发出请求时都需要完成TCP 握手流程,这种三次握手非常消耗时间,为了抵消这些握手带来的代价,HTTP/1.1 推出了持续作用(keep-alive)这一概念,如果客户端将 connection 报头设为 keep-alive,服务器在成功发出响应后将不会关闭连接,而是允许客户端重复利用已经建立的连接来进行其他请求。注意,在上个请求的响应完全传输之前,你依然可以发送请求。这么做使得网络开发者尽量减少其他资源的数量。充分利用他们的六个连接。这就是JavaScript 和 CSS 文件通常都捆绑到一起图片也会被加工为精灵图的原因,仅用一个请求就能获得捆绑包。
稍后我们将了解 HTTP/2如何解决队头阻塞问题。
在深入学习 HTTP/2 之前,我们应该讨论下 HTTPS 加密,它是一个非常容易被误解的概念。很多人认为它只是针对企业和电子商务网站,这绝对是个错误的认识。