Fork me on GitHub

小结http

network/http/http_banner

了解http是前端工程师必备的一个技能哈,虽然现在自己不是很了解,但是根据查阅的资料,自己谈下自己的总结啦!路漫漫兮其修远…

概述

Web使用一种名为HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。而协议是指规则的约定。可以说,Web是建立在HTTP协议上通信的。

HTTP是干什么的?

http是数据传输协议(超文本传输协议),用来沟通客户端和服务器。

什么是资源?

网络上的一切内容皆资源,无论是静态文件还是动态生成的代码等。

什么是媒体类型?

最初设计MIME(Multipurpose Internet Mail Extension,多用途英特网邮件扩展)是为了解决在不同的电子邮件系统之间搬迁报文时存在的问题。MIME在电子邮件系统中工作得非常好,因此HTTP也采纳了它,用它来描述并标记多媒体内容。

其实多媒体类型就是一种数据类型的标记,用来告诉接收端,接收到的数据是什么类型,让接收端知道怎么才能处理该文件。常见的标记方式就是MIME(见上解析),MIME描述了文件的主要类型以及特定子类型,例如:"Content-Type":"text/html",其中text描述的文件主要类型是文本,而其特定类型是html文档!

怎么理解URI以及它的子集(URL,URN)

URI(Uniform Resource Identifier,统一资源标志符)的作用就是在网络上确定唯一资源,这就好比,在中国,身份证能唯一确定一个人一样。知道身份证号,就一定能确定一个人的信息。

URL(Uniform Resource Locator,统一资源定位符)是跟资源在网络上的位置有关,比如文章的banner图的位置为http://omu538iq8.bkt.clouddn.com/network/http/http_banner.jpg,广义上讲,我们说的URI就是指URL。

URN(Uniform Resource Name,统一资源名称)是作为特定内容的唯一名称使用的,与目前的资源所在地无关。URN是未来的趋势(试想一下人不可能是在一个地理位置不动吧,而ID_card的一定不会变的),不过貌似具体实施还在商讨中。

什么是事务

事务就是一次http连接(不包括tcp/ip连接,只包括一次http报文发送与接收)的整个过程,由请求命令和响应结果组成。中间数据格式是http报文。本文的banner图示就是一次http的事务。我们平常打开一个网站,里面包括很多事务,比如:请求网页文档、请求某张图片以及请求某个视频/音频。

方法指什么?

HTTP方法会告诉服务器要执行什么动作(获取一个web页面、运行一个网关程序、删除一个文件等)。这些方法包括GET , PUT , DELETE , POST , HEAD

状态码有什么用?

状态码是一个三位数字的代码,告知客服端请求是否成功,或者是否需要采取其他动作。状态码带着一个原因短语,方便人解读,比如304 Not Modified ,当发送GET请求资源返回上面的代码时候,可以解读成:客户端已经执行了GET,但文件没发生改变(和上次请求的资源一模一样)

简单介绍一些报文

首先报文是http协议一种纯文本的数据格式,分为请求报文和响应报文,两种报文都具有类似的结构,分别由三部分构成:起始行、首部、主体。起始行描述了报文干了什么;首部描述报文传输的具体细节;主体描述传输的实际内容。

什么是TCP/IP?更HTTP有什么关系?

TCP/IP是全世界的计算机和网络设备常用的层次化交换网络协议集。简单说,HTTP协议是一个应用层协议,位于TCP/IP协议的上一层,TCP/IP协议的主要作用就是过滤掉每个计算机的差异性,隐藏相关弱点,使得对于HTTP协议来说提供的都是”相同的”接口。

在一次网络请求中,经历了哪些过程?

(a).浏览器从RUL中通过解析出服务器的主机名

(b).浏览器将服务器的主机名转换成服务器的IP地址

(c).浏览器将端口号(如果有的话,默认是80)从URL中解析出来

(d).浏览器建立一条与web服务器的TCP连接

(e).浏览器向服务器发送一条HTTP请求报文

(f).服务器向浏览器回送一条HTTP响应报文

(g).关闭连接,浏览器显示文档

HTTP协议有哪些版本?

HTTP/0.9:这个协议有很多严重的设计缺陷;

HTTP/1.0:使用广泛;

HTTP/1.0+:是非官方的HTTP/1.0的扩展版本;

HTTP/1.1:是目前正在广泛使用的版本,修复相关的设计缺陷,增加相关特性;

HTTP-NG(又名HTTP/2.0):将来使用与否正在商讨中

Web的一些结构组件

上面有介绍了两个应用程序(Web浏览器和Web服务器)是如何互相发送报文来实现基本事务处理的。下面将列其他一些比较重要的应用程序,如下:

代理:位于客户端和服务器之间的HTTP中间实体。具体来说就是代理位于客户端和服务器之间,接收所有客户端的HTTP请求,并把这些请求转发给服务器(可能会对请求进行修改之后转发)。对于用户来说,这些应用程序就是一个代理,代表用户访问服务器。代理的主要作用有过滤、屏蔽等,比如,在企业中对下载的应用程序进行病毒检测,
或者对小学生屏蔽一些成人才能看的内容。(注意⚠️ 代理即可以代表服务器对客户端进行响应,又可以代表客户端对服务器进行请求)

缓存(cache):HTTP的仓库,使常用页面的副本可以保存在离客户端更近的地方。首先说明一下:缓存某种意义上来说是一种代理服务器。它主要使用代表服务器对客户端进行响应。发送于预先缓存好的资源的副本(浏览器上就有缓存哈)。这样会加快事务响应速度、同时也会减少服务器的负载、减轻带宽等问题。

网关(gateway):是连接其他应用程序的特殊的web服务器。网关是一种特殊的服务器,面对客户端时好像它就是服务器,而对于服务器,它又充当客户端的角色,它的主要作用就是协议转换。例如下面的HTTP/FTP网关。

network/http/gateway

隧道(tunnel):对HTTP通信报文进行盲转发的特殊代理。HTTP隧道通常用来在一条或多条HTTP数据,转发时不会窥探数据。

Agent代理:发起自动HTTP请求的半只能Web客户端。说白了就是我们平时所说的浏览器,以及web机器人、爬虫等。

URL和资源

上面提到过,URN还没成熟,说的URI可以等同说URL,即URI == URL , URI !== URL

URL的语法

下面是URL的组成:

1
2
3
4
5
6
7
8
9
10
11
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

# scheme:方法描述了请求资源时用了什么协议,用“:”与url其它部分隔开;
# user:用户名描述了访问是带的用户名
# password:密码描述了用户名后面可能跟的密码,用“:”跟用户名隔开;
# host:主机描述了网站主机名或ip地址,如果前面有用户名和密码,用@分开;
# post:服务器当前正在监听的端口,http默认为80,https默认为443;
# path:路劲描述了资源在服务器上的位置,用‘/’跟前面部分隔开;
# params:参数描述了请求需要附加的参数,用“;”与其他部分隔开;
# query:查询是用来激活服务器程序去执行某些操作,比如查询数据库等,用“?”与其余部分隔开;
# frag/fragments:片段只在客户端使用,不发送到服务器端;

URL快捷方式

URL快捷方式描述了一个程序如何通过相对地址解析处绝对地址的过程以及在浏览器地址栏输入部分URL浏览器自动补全主机名的一种机制。

相对地址转换为绝对地址:首先会根据一个基础地址来得到出协议、主机名、端口等。

浏览器扩展地址主要通过主机名扩展和历史扩展等方式实现自动地址补全。

URL编码

为什么需要编码?

主要从URL的一致性、安全性、以及完整性来强调需要对URL字符进行编码。比如因为一个URL连接的两端可能出现的机器种类很多,为了让大家能够解析出一个相同的url,所以有必要对某些不安全的URL字符进行转义。

URL字符集由什么编码构成?

早起的URL是由US-ASCII码编码,但是随着网络全世界的流行,有很多字符是US-ASCII不能编码的,因为US-ASCII码最多只能编译127个字符。通过转义序列,就可以用US-ASCII字符集的有限子集字符值或数据进行编码了。

编码机制?

为了避开安全字符集表示法带来的限制,人们设计了一种编码机制,用来在URL中表示各种不安全的字符。这种编码机制就是通过一种“转义”表示法来表示不安全字符的,这种转义表示法包含一个百分号(%),后面跟着两个表示字符的ASCII码的十六进制数。

哪些字符不建议在URL里面使用?

在URL中,有几个字符被保留起来,有着特殊的含义。有些字符不在定义的US-ASCII可打印字符集中。还有些字符会与某些因特网网关和协议产生混淆,因此不赞成使用,比如“%”。

HTTP报文

如果说HTTP是因特网的信使,那么HTTP 报文就是它用来搬东西的包裹了。我们将了解:

  1. 报文是如何流动的
  2. HTTP报文的三个组成部分(起始行、首部和实体的主体部分)
  3. 请求和响应报文直接的区别
  4. 请求报文支持的各种功能(方法)
  5. 和响应报文一起返回的各种状态码
  6. 各种各样的HTTP首部都是用来干什么的

报文流

HTTP报文是以一种类似的流方式来发送数据的,所以报文流讲述了HTTP报文的一些客观状态,相关的术语:流入、流出形容事物的处理。HTTP报文任何时候是从上流流入,其中经过的节点既可能是上流,也有可能是下流,如果从某个节点流出,那么相对于此节点流入的那个节点就是上游,翻过它就是下游。

报文的组成部分

报文是由三部分组成:起始行、首部、主体。起始行和首部都是ASCII文本,而主体可以是任意类型文件,比如二进制,视频等。且起始行和首部都以一个crlf作为结束符,并且首部与主体之间应始终存在一个以crlf序列作为结束的空行。当然了,为了兼容老版本的http,这里有时并不是那么严格要求非要crlf同时存在。

请求报文和响应报文直接的区别

两者的报文语法如下:

1
2
3
4
5
# 请求报文 
<method><request-URL> <version>
<headers>

<entity-body>
1
2
3
4
5
# 响应报文
<version> <status> <reason-phrase>
<headers>

<entity-body>

上面的请求报文和响应报文的字段解析如下:

1
2
3
4
5
6
7
# method是客户端希望执行的动作,如GET、POST等
# request-URL是指请求资源的路径
# version报文版本号,格式为http/<major>.<minor>,分别代表主要版本和次要版本号,其含义应分开理解
# status就是用一个三位的数字表示当前事务处于什么状态,便于开发者处理
# reason-phrase原因短语,方便查看状态码的意思
# headers首部是一个包含零个或多个的键值对,键值对以crlt隔开,而键,值之间以":"隔开,期间包含一个可选的空格
# 任意格式组成的数据块,也是实际发送的内容

请求报文支持的方法

安全方法

能在服务器端操作的就是非安全方法,比如DELETE、PUT、POST,不在服务器端游操作的就是安全方法,比如GET、HEADER。当然了,安全方法并非不能在服务器端有操作,这是开发者可以控制的。

GET

用来请求服务器端发送某个资源。

HEADER

此方法跟GET方法类似,区别就是不返回主体。HEAD请求的回应部分的HTTP头部中包含的信息与通过GET请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到Request-URI所标志的资源的信息。常用于测试超链接的有效性,是否可以访问,以及最近是否更新。

PUT

用于向服务器端修改、插入数据。

POST

用于向服务器端发送数据。常用于表单的提交,用于登录注册页面。

TRACK

用于向服务器端请求报文在发送过程中经过了什么修改,主要是用来测试。

OPTIONS

用来请求服务器告知其支持什么功能。

DELETE

用于向服务器删除某个指定的资源。

状态码

#类别原因短语
1XXInformational(信息性状态码)接收的请求正在处理
2XXSuccess(成功状态码)请求正常处理完毕
3XXRedirection(重定向状态码)需要进行附加操作以完成请求
4XXClient Error(客户端错误状态码)服务器无法处理请求
5XXServer Error(服务器错误状态码)服务器处理请求出错

常见的状态码

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
34
35
36
37
38
39
40
41
42
43
44
200 OK
# 表示从客户端发过来的请求在服务器端被正常处理了

204 No Content
# 表示服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分

206 Partial Content
# 表示客户端进行了范围请求



301 Moved Permanently
# 永久性重定向。该状态码表示请求的资源已经被删除,重新分配了新的URI,以后应使用资源现在所指的URI

302 Found
# 临时性重定向。该状态码表示请求分配的资源已被分配了新的URI,希望用户(本次)能使用新的URI访问。和301状态相似,但是302代表的资源不是被永久转移,只是临时性质的。

303 See Other
# 该状态码表示由于请求对应的资源存在着另一个URI,应该使用GET方法定向获取请求的资源。

304 Not Modified
# ⚠️ 该状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况。304状态码返回时,不包含任何响应的主体部分。304虽然被划分到3XX类别里面,但是和重定向没有关系。



400 Bad Request
# 表示请求报文中存在语法错误。

401 Unauthorized
# 表示发送的请求需要有通过HTTP认证(BASIC认证、DIGEST认证)的认证信息。

403 Forbidden
# 表示对请求资源的访问被服务器拒绝了。

404 Not Found
# 表示服务器上无法找到请求的资源。



500 Internal Server Error
# 表明服务器端执行请求时发生了错误

503 Server Unavailable
# 表明服务器暂时处于负载或者正在进行停机维护,无法处理请求。

更多的状态码请自行百度。

HTTP首部

首部和方法配合工作,共同决定了客户端和服务器能够做什么事情。首部分为通用首部、请求首部、响应首部、主体首部、扩展首部!具体的信息请查看《HTTP权威指南》。

代理

Web代理(proxy)服务器是网络的中间实体。代理位于客户端和服务器之间,扮演“中间人”的角色,在各端点之间来回传送HTTP报文。

缓存

web缓存是可以自动保存常见文档副本的http设备。当web请求抵达缓存时,如果本地有已缓存的副本,就可以从本地存储设备而不是原始服务器中提取这个文档。使用缓存的优点有:

  1. 缓存减少了冗余的数据传输,节省了你的网络费用。
  2. 缓存缓解了网络的瓶颈问题。不需要更多的带宽就能更快的加载页面。
  3. 缓解降低了对原始服务器的要求。服务器可以更加快地响应,避免过载的出现。
  4. 缓存降低了距离时延,因为从较远的地方加载页面会更慢些。

冗余的数据传输

每次从服务器上拿数据(客户端频繁访问同一个页面),那么带来的后果就是:服务端多次发送重复的数据浪费流量、耗费昂贵的网络带宽从而减低传输速率、加大服务器的负载。而有了缓存之后,这些问题可以迎刃而解。

带宽瓶颈

很多本地的网络客户端提供的带宽比远程服务器提供的带宽要宽。客户端会以路径上最慢的网速访问服务器,这样本地的带宽优势就没有体现出来。如果在客户端方向配置一个高速缓存服务器,那么就可以很快得到响应,由此也可以看出带宽对报文传输速率的影响。

瞬间拥塞

瞬间拥塞描述的是一种情况:一个爆炸性的新闻和热点事件,如果没有配置缓存的情况下,那么在短时间内,服务器会收到突变的请求增长,负荷会爆炸性增长,肯定会吃不消。但是又了缓存,可以大大分担服务器的负载数量。

距离时延

距离时延说明的一个问题就是传输数据过程这个过程需要的时间,而且路程越长,那么需要的时间也会越多,即时延越长。所以在距离客户端较近的地方部署缓存服务器,减少了传输路程,那么就减少了传输时延。平时使用的cdn就是这个原理啦。

命中与未命中

  • 缓存命中与缓存未命中:一次http事务请求如果是从得到的响应是从缓存得到的原始副本,那么这样的过程就称之为缓存命中。如果缓存没有响应的副本,而要去请求原始服务,那么久把这个过程称之为缓存未命中。

  • http再验证:原始响应内容是在变化的,所以缓存应该在文档过期时间之后去验证缓存的副本是不是新鲜的,这个过程就叫做http再验证。如果再验证之后得知副本是新鲜的,那么原始服务器就会返回304 not modified。此时,称之为再验证命中或者缓存慢命中。如果得知缓存不是新鲜的,那么服务器返回200 ok。此时,称之为再验证未命中。如果原始对象被删除,返回404 not found响应。响应的缓存副本要删除。

  • 命中率:指由缓存返回副本事务在全部事务中所占的比例,称之为缓存命中率。这个数据实际意义不是很大,而字节命中率从资源大小总量的角度说明缓存命中所占的比例。因为它从数据流量的角度出发,所以实际中这个数据的意义挺大的。

  • 区分命中和未命中:简单来说,http没有相应的机制来告知客户端响应是从缓存得到的还是从原始服务器得到的。但是我们可以从http响应报文首部中的date字段得知这一情况:如果这个字段的时间比当前时间更早得多,说明这是从缓存得到的,因为date描述的服务器第一次响应的时间,而缓存是不会对这个字段进行修改的。

缓存的拓扑结构

  • 分类:缓存分为私有缓存(只为一个客户端服务,比如我们给浏览器配置的代理)和共有缓存(为多个客户端服务,现实中是以代理缓存服务器的形式出现)

  • 代理缓存的层级结构:此种结构描述的以父、子层级出现的层级结构,同时离客户端越近的子缓存命中率较低(较廉价),可以把请求上升到父缓存(较昂贵),从而在父缓存那里实现事务处理。

  • 代理缓存的网状结构:它描述的缓存结构并不是很明显呈现父子关系的结构,而是呈现无规则的网状。这种结构的思想就是子缓存可以动态选择上一级缓存,从而实现更灵活的缓存控制。

缓存的处理步骤

  1. 接收————缓存从网络中读取抵达的请求报文。
  2. 解析————缓存对报文进行解析,提取出url和各种首部。
  3. 查询————缓存查看是否有本地副本可用,如果没有,就去获取一份副本(根据情形和配置,到原始服务器或父代理中去取,将副本存在本地,或者获取不到返回错误信息)
  4. 新鲜度检测————缓存查看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新。
  5. 创建响应————缓存会用新的首部和已缓存的主体来构建一条响应报文。
  6. 发送————缓存通过网络将响应发送给客户端。
  7. 日志————缓存可选地创建一个日志文件条目来描述这个事务。

保存副本的新鲜度

  • 文档过期通过特殊的http首部cache-control和expires,http让原始服务器为每个文档设置一个“过期时间”,如:
1
2
3
4
5
Cache-Control: Max-Age = 484200  // 除了Max-Age , 还可以有其他的字段啦
Expire: Fri, 28 Oct 2016 12:00:00 GMT

// Max-Age 是相对时间,以秒为单位,理解为使用期 推荐使用
// Expires 为绝对时间,理解为到期时间 不推荐使用--由于很多服务器的时钟都不同步,或者不正确,所以最好使用剩余秒数(相对时间)来表示过期时间
  • 服务器再验证:仅仅是已缓存文档过期了并不意味着它和原始服务器目前处于活跃状态的文档有诗集的区别;这知识意味着到了要进行核对的时间了。这种情况被称为服务器再验证,说明缓存需要询问服务器是否发生了变化。

  • 用条件再验证:涉及到的两个首部为If-Modified-SinceIf-None-Match。如下:

1
2
3
4
5
If-Modified-Since: <data>
If-None-Match: <verson>

// date为服务器响应报文里面Last-Modified时间
// version是实体标签ETag。其机制跟If-Modified-Since不同在于:后者是根据修改时间来判断文档的新鲜度,但是有些情况下是不适合的,比如我们只是加了注释什么的,其中实际内容并没有什么变化。

缓存的控制能力

  • 缓存控制能力描述的是服务器可以通过设置相关的首部来控制文档的缓存过期时间的能力。相关首部解析如下:
指令目的
Cache-Control:no-store不能缓存/尽快从存储器中删除文档的所有痕迹,因为里面可能有敏感信息
Cache-Control:no-cache除非资源进行了再验证,否则这个客户端不会接受已缓存的资源
Cache-Control:must-revalidate严格遵守新鲜验证规则
Cache-Control:max-age设置多长时间过期(相对时间)
Expires:设置多长时间过期(绝对时间)不建议使用
试探性过期不设置首部,让缓存来决定,这个方式涉及到一种算法,比如缓存服务器通过查看最后修改时间,从而得到该文档的修改频繁度,从而为其设置缓存过期时间

上面的优先级从上到下依次降低。

  • 客户端的新鲜度限制:web浏览器都有refresh(刷新)或者reload(重载)按钮,可以强制对浏览器或者代理缓存中可能过期的内容进行刷新。refresh按钮会发布一个附加了cache-control请求首部的get请求,这个请求会强制进行再验证,或者无条件地从服务器获取文档。refresh的确切行为取决于浏览器、文档以及拦截缓存的配置。客户端可以用cache-control请求首部来强化或者放松对过期时间的限制,相关的首部介绍如下:
指令目的
Cache-Control: max-stale =缓存可以随意提供过期的文件。如果指定了参数,这段时间内,文档就不能过期。这条指令放松了缓存的规则
Cache-Control: min-fresh =至少在未来秒内文档要保持新鲜。这就使缓存规则更加严格了
Cache-Control: max-age =缓存无法返回缓存时间长于秒的文档。这条指令会使缓存规则更加严格,除非同时还发送了max-stale指令,在这种情况下,使用期可能会超过其过期时间
Cache-Control: no-cache Pragma: no-cache除非资源进行了再验证,否则这个客户端不会接受已缓存的资源
Cache-Control: no-store缓存应该尽快从存储器中删除文档的所有痕迹,因为其中可能会包含敏感信息
Cache-Control: only-if-cached只有当缓存中有副本存在时,客户端才会获取一份副本

设置缓存控制

不通的web服务器为HTTP Cache-Control 和 Expiration首部的设置提供了一些不同的机制。下面讲解下面这些:

  1. 控制Apache的HTTP首部

默认没有开启,需要进行相关的配置:mod_headers,mod_expires,mod_cern_meta

  1. 通过HTTP-EQUIV控制HTML缓存

例子如下:

1
2
3
4
5
6
<html>
<head>
<title>this is the title</title>
<meta HTTP-EQUIV="Cache-control" CONTENT="no-cache"/>
</head>
...

此方法只是对html文件有用,并不是很好。

内容太多,一篇文章hold不住,会进行分知识点来写~

参考

《HTTP权威指南》

《图解HTTP》

<-- 本文已结束  感谢您阅读 -->
客官,且步,赏一个呗 (@ ~ @)