HTTP协议相关

Http协议


(一)从输入URL到页面加载发生了什么

1. 在浏览器中输入URL

kwLPS.md.png

2. 浏览器经过域名去找对应的IP

  • 浏览器缓存-浏览器时不时会缓存DNS记录,OS并无明确指明浏览器每条记录的生命周期是多长,因此浏览器按期的缓存DNS记录(大概2-30分钟不等)。下图为chrome浏览器缓存记录(chrome://net-internals#dns

kwKTH.md.png

  • 系统缓存-若是缓存中没有,就去调用gethostbyname库函数(操做系统不一样函数也不一样)进行查询。函数在试图进行DNS解析以前首先检查域名是否在本地Hosts文件里,Hosts文件的位置,不一样的操做系统也有所不一样。
  • 路由缓存-若是gethostbyname没有这个域名的缓存记录,也没有在hosts里找到,它将会向DNS服务器发送一条DNS查询请求。DNS服务器是由网络通讯栈提供的,一般是本地路由器或者ISP的缓存DNS服务器。
  • ISP DNS缓存-查询本地网络提供商的DNS服务器。
  • 递归查找

3.浏览器向服务器发送一个HTTP请求

因为srs.testpub.cn页面是动态的,因此浏览器不会从缓存里读页面的内容,浏览器会向服务器发送HTTP请求,请求可能以下所示:php

GET http://facebook.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...]
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...]
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: facebook.com
Cookie: datr=1265876274-[...]; locale=en_US; lsd=WW[...]; c_user=2101[...]

GET请求的URL是“http://facebook.com”,浏览器经过(User-Agent header)来代表本身是谁,以及本身接受什么样类型的响应(Accept and Accept-Encoding headers)。Connection header告诉服务器不要关闭TCP链接以便为后来请求所重用。css

请求中还会带上cookie,cookie就是一些键值对,能够用来保持不一样页面请求间的状态。所以cookie能够储存登陆的用户的名称,服务器为用户分配的惟一密码以及一些用户设置信息等。cookie是存在客户端的,每次客户端向服务器发送请求都会带上cookie。html

4.facebook服务器发出重定向响应

服务器给出以下响应:前端

HTTP/1.1 301 Moved Permanently
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
      pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Location: http://www.facebook.com/
P3P: CP="DSP LAW"
Pragma: no-cache
Set-Cookie: made_write_conn=deleted; expires=Thu, 12-Feb-2009 05:09:50 GMT;
      path=/; domain=.facebook.com; httponly
Content-Type: text/html; charset=utf-8
X-Cnection: close
Date: Fri, 12 Feb 2010 05:09:51 GMT
Content-Length: 0

这告诉浏览器应该访问的是“http://www.facebook.com”而不是“http://facebook.com/”。而之因此重定向的缘由,就是为了增长域名的权重,在这里即增长了www.facebook.com域名的权重。nginx

5.浏览器跟随重定向

浏览器向“http://www.facebook.com/”发送请求web

GET http://www.facebook.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...]
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...]
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cookie: lsd=XW[...]; c_user=21[...]; x-referer=[...]
Host: www.facebook.com

6. 浏览器开始处理请求

浏览器开始处理请求并返回响应。ajax

  • Web服务器软件

web服务器软件,如IIS(
Internet Information Services-互联网信息服务)或Apache接收到HTTP请求,决定哪一个处理器来处理该请求。一个请求处理器是一个程序(可由ASP.NET、PHP、Ruby或其余语言编写)用来读请求并生成响应的HTML。最简单的例子,一个请求处理器可被储存在一个文件结构中,该文件结构映射URL结构,好比URL:http://example.com/folder1/page1.aspx对应文件/httpdocs/folder1/page1.aspx。web服务器软件可配置,所以URL可由被手动映射到请求处理器,所以公page1.aspx的公有URL可由是http://example.com/folder1/page1chrome

  • 请求处理器

请求处理器读取请求,请求参数,cookie。读取过程当中有可能更新某些数据到服务器端。而后,请求处理器会生成一个HTML格式的响应。跨域

7.服务器返回HTML响应

HTTP/1.1 200 OK
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
    pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
P3P: CP="DSP LAW"
Pragma: no-cache
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
X-Cnection: close
Transfer-Encoding: chunked
Date: Fri, 12 Feb 2010 09:05:55 GMT

Content-Encoding header告诉浏览器响应的body是被gzip给压缩过的,将body解压以后,本来的HTML就显示出来了。浏览器

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"   
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
      lang="en" id="facebook" class=" no_js">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-language" content="en" />
...

除了解压方式以外,headers还会告诉浏览器如何缓存页面等,总之headers很重要。

8.浏览器开始渲染HTML

9.浏览器发送请求去获取HTML中的一些内嵌对象

浏览器会开始获取页面上的一些引用资源,好比:

Images
http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif
http://static.ak.fbcdn.net/rsrc.php/zBS5C/hash/7hwy7at6.gif
…
CSS style sheets
http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css
http://static.ak.fbcdn.net/rsrc.php/zANE1/hash/cvtutcee.css
…
JavaScript files
http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js
http://static.ak.fbcdn.net/rsrc.php/z6R9L/hash/cq2lgbs8.js
…

每个请求都是跟上面的GET请求差很少,都要通过dns解析等一系统过程。
不过静态文件是能够被浏览器缓存的,因此有一些静态文件浏览器可能直接从缓存里读取,而不须要去服务器端读。能够经过chrome://cache/来查看浏览器缓存。
lHtm2.md.png

10.浏览器发送异步的AJAX请求

AJAX = 异步Javascript和XML。
AJAX是一种用于建立快速动态网页的技术。经过在后台与服务器进行少许的数据交换,AJAX可使网页实现异步更新。这意味着能够在不从新加载整个网页的状况下,对网页的某部分进行更新。


(二)HTTP协议概述

HTTP是一种可以获取如HTML这样网络资源的协议。它是Web上数据交换的基础,是一种client-server协议,也就是说请求一般是由像浏览器这样的接收方发起的。一个完整的web文档是由不一样的子文档从新组合而成的,像是文本、布局描述、图片、视频、脚本等等。

客户端和服务器端经过交换各类的信息(与数据流正好相反)来进行交互。一般由像浏览器这样的客户端发出的消息叫requests,被服务器端回应的消息就叫作responses。

HTTP被设计于20世纪90年代,是一种可扩展性的协议,他是应用层的协议,虽然理论上能够经过任何可靠的传输协议来发送,可是仍是经过TCP或者TLS-加密的TCP链接来发送。由于由很好的扩展性,时至今日不只被用来传输超文本文档,还用来传输图片、视频或向服务器发送如HTML表单这样的信息。HTTP还能够根据网页的需求,来获取部分web文档的内容来更新网页。

HTTP协议的参与者

HTTP是一个client-server协议:请求经过一个实体被发出,实体也就是用户代理。大多数状况下,这个用户代理都是指浏览器,固然它也多是任何东西,好比一个爬取网页来生成河维护搜素引擎索引的机器。

每个发送到服务器的请求,都会被服务器处理而且返回一个消息,也就是response。在client与server之间,还有许许多多的被称为proxies的实体,他们的做用与表现各不相同,好比有些是网关,还有些是caches等。
lXg9d.md.png
实际上,在一个浏览器和处理请求的服务器之间,还有计算机、路由器、调制解调器等等许多实体。因为Web的层次设计,那些在网络层和传输层都不可见了。HTTP是在最上层应用层中的,虽然下面的层次对分析网络问题很是重要,可是对HTTP的描述老说,这些大多数都是不相干的。

1.客户端:user-agent

严格意义来讲,user-agent就是任何可以表现出用户通常行为的工具。但实际上,这个角色一般都是由浏览器来扮演的。

简单来讲user-agent就是来者何人,留下姓名的意思。

对于发起请求来讲,浏览器老是做为发起一个请求的实体,而永远不是服务器(虽然一些机制已经可以模拟服务器发起请求的消息了)。

要渲染出一个网页,浏览器首先要发送第一个请求来获取这个页面的HTML文档,再解析它并根据文档中的资源信息发送其余的请求来获取脚本信息,或者CSS来进行页面布局渲染,还有一些其余的页面资源(如图片和视频等)。而后,它把这些资源结合到一块儿,展示出来一个完整的文档,也就是网页。打开一个网页后,浏览器还能够根据脚本内容来获取更多的资源来更新网页。

一个网页就是一个超文本文档,也就是说由一部分显示的文本多是连接,启动它(一般是鼠标的点击)就能够获取一个新的网页。网页使得用户能够控制它的user-agent来导航Web。浏览器来负责翻译HTTP请求的命令,并翻译HTTP的返回消息让用户能明白返回消息的内容。

2.Web服务端

在上述通讯过程的另外一端,就是一个Web Server来服务并提供客户端请求的文档。Server至少虚拟意义上:它能够是许多共同分担负载(负载平衡)的一组服务器组成的计算机群,也能够是一种复杂的软件,经过向其余计算机发起请求来获取部分或所有资源的软件。

Server再也不只是一个单独的机器,它能够是在同一个机器上装载的许多服务之一。在HTTP/1.1和Host头部中,它们甚至能够共享同一个IP地址。

3.Proxies

在浏览器和服务器之间,有许多计算机和其余设备转发了HTTP的消息。由于Web栈层次结果的缘由,它们大多数都出如今传输层、网络层和物理层上,对于HTTP的应用层来讲就是透明的(虽然它们可能会对应用的性能有重要影响)。而还有一部分表如今应用层上的,就叫作proxies(中文翻译为代理)了。Proxies既能够表现得透明,又能够不透明(看请求是否经过它们),主要表如今这几个功能上:

  • 缓存(能够是公开的或私有的,像浏览器的缓存)
  • 过滤(像反病毒扫描,家长监护)
  • 负载均衡,让多个服务器服务不一样的请求
  • 对不一样资源的权限控制
  • 登陆,容许存储历史信息

HTTP的基本性质

HTTP是简单的

即使在HTTP/2中把HTTP消息封装到了frames中,HTTP大致上仍是被设计成可读的并且简单的。HTTP的消息可以让人读懂且明白它的意思,还容许见得测试,放低了门槛,更有利于新来者了解。

HTTP是可扩展的

在HTTP/1中就出现了,HTTP Headers让协议扩展变得很是容易。只要服务端和客户端在新的headers上语义达成一致,新的功能就能够轻松地被加进来。

HTTP是无状态的,有会话的

HTTP是无状态的:在同一个链接中,两个成功执行的请求之间是没有关系的。
而HTTP的核心是无状态的,cookies的使用能够建立有状态的会话。

HTTP和链接

一个链接是由传输层来控制的,基本不属于HTTP的范围内。然而HTTP并不须要下面传输层的协议是面向链接的,它只须要它是可靠的,就是说不能丢失消息(至少没有错误)。在因特网两个最经常使用的传输层协议中,TCP是可靠的,而UDP不是。所以,HTTP依赖于TCP进行消息传递,虽然TCP是面向链接的,但这并非必须的。

HTTP/1.0曾经为每个请求/回应交换都打开一个TCP链接,致使了2个缺点:打开一个链接须要屡次的消息往返所以很慢。可是当多个消息周期性发送时,这就变得更加高效:暖链接比冷链接更高效。

为了减轻这些负担,HTTP/1.1引入了流水线的概念和持久链接的概念:下层的TCP链接能够经过Connection头部来被部分控制。经过一个链接多个消息的方式来让这个链接始终保持为暖链接。

为了更好的适合HTTP,设计一种更好的传输层协议就一直在进行中,Google就研发了一张以UDP为基础,能提供更可靠更有效传输层协议的QUIC。

HTTP能控制什么

  • 缓存

文档怎么缓存可以经过HTTP来控制。服务器端告诉代理和客户端什么须要被缓存,缓存多久,而客户端可以命令中间缓存代理来忽略存储的文档。

  • 开放同源限制
    HTTP能够经过修改头部来开放浏览器强制对Web网址作的分割限制。

  • 认证
    基本的认证功能(Basic Authenticate)能够直接经过HTTP提供,使用Authenticate类似的头部就能够,或者用HTTP cookie来设定指定的会话。

  • 代理
    服务器和客户端一般都处于内部网上,HTTP请求就要经过代理穿过网络障碍,但不是全部的代理都是HTTP代理的。

  • 会话
    Cookies用一个服务端的状态链接起每个请求。这就建立了会话,虽然基本的HTTP协议是无状态协议。这颇有用,不只是由于能用的购物车这样的电商业务上,更是由于,是的任何网站都可以配置页面展示的东西。

HTTP流

当客户端想要和服务端进行信息交互时(服务端是指做为最终的服务器,或者是做为中间代理),过程表现为下面几步:

  1. 打开一个TCP链接(或者重用以前的一个):TCP链接用来发送一条或多条请求,固然也用来接受回应消息。客户端可能重用一个已经存在的链接,或者也可能重开几个新的与服务端的TCP链接。

  2. 发送一个HTTP报文:HTTP报文(在HTTP/2以前)是语义可能的。 在HTTP/2中,这些简单的消息被封装在了帧中。这使得报文不可能被直接读出来,可是规则仍旧是相同的。

GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
  1. 读取服务端返回的报文:
HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
  1. 关闭链接或者为之后的请求重用链接。

HTTP报文

HTTP/1.1和更早的HTTP报文都是语义可读的。在HTTP/2中,这些报文被嵌入到了一个新的二进制结构中 - 帧。帧能够容许实现颇有优化,如复用和报文头部的压缩。即便只有原始HTTP报文的一部分以这种HTTP/2版本的方式发送出来,每一个报文的语义依旧不变,客户端会重组原始的HTTP/1.1请求。所以用HTTP/1.1格式来考虑HTTP/2报文依旧有效。

有两种HTTP报文的类型,请求与响应,每种都有其特定的格式。

请求

HTTP请求的一个例子:

GET / HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1

请求由厦门的元素组成:

  • 一个HTTP的method,常常是由一个动词像GET, POST或者一个名词像OPTIONS,HEAD来定义客户端的动做行为的。一般客户端的操做都是获取资源(用GET方法)或者发送一个HTML form表单的值(用POST方法),虽然在一些状况下也会有其余的操做。
  • 要获取的资源的路径,一般是上下文中就很明显的元素的URL,它没有protocol(http://),domain(developer.mozilla.org),或是TCP的port(HTTP是80端口)
  • HTTP协议的版本号
  • 为服务端表达其余信息的可选择性的headers
  • 对于一些像POST这样的方法,报文的body就包含了发送的资源,这个body与回应报文的body相似

响应

HTTP响应的一个例子:

HTTP/1.1 200 OK
Bdpagetype: 2
Bdqid: 0xa10573290003626a
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Wed, 18 Apr 2018 08:23:03 GMT
Expires: Wed, 18 Apr 2018 08:23:03 GMT
Server: BWS/1.1

响应报文包含下面的元素:

  • HTTP的版本号
  • 一个状态码(status code),来告知对应的请求发送成功或失败,以及失败的缘由
  • 一个状态信息,这个信息是非权威的状态码描述信息,也就是说能够由服务器咨询设定的
  • HTTP headers,与请求的很像
  • 可选的,可是比在请求报文中更加常见地包含获取资源的body

总结

HTTP是很简单可扩展的一直协议。结合了轻松添加头部信息能力的Client-server结构使得HTTP能够和Web的功能扩充一同发展。

即便HTTP/2为了提升性能把HTTP报文嵌到HTTP报文帧中这一举措增长了复杂度,可是从Web应用的角度看,报文的基本结束是没有变化的,从HTTP/1.0发布起就是相同的。会话流依旧很简单,用一个简单的HTTP message monitor就能够查看它和debug。


(三)实战Chrome开发者工具

步骤

  • 打开chrome浏览器,输入网址:itest.info
  • 按F12打开chrome开发者工具,并选择Network标签
  • 刷新页面
  • 找到itest.info请求

lbijA.md.png

结果(查看headers标签)

1. General

Request URL: http://www.itest.info/
Request Method: GET
Status Code: 200 OK
Remote Address: 119.29.203.242:80
Referrer Policy: no-referrer-when-downgrade

2. Response Headers

Cache-Control: max-age=0, private, must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Thu, 19 Apr 2018 01:19:54 GMT
ETag: W/"f64211eeefa54e7f13f091bb162d68f4"
Server: nginx/1.10.3 (Ubuntu)
Set-Cookie: _itest5_session=T0NTeUQ0OGFxaTl5aWR5MG4zTDlzUjJ3U3pNUWNvK096YkROcnVhL2w5clMrdGk5UGNUaTliaFNuM1F1R2hxWTBCOUpTd1BLRXNSNjkvbXQ5YUppZVJaZWxiZ3dMcnJVQTN0UWJqUFlFNTV1Zng3UnJ0ZnJYV0Z1NjBWSW9DV1gvNXA0a3hHR3J5YmV3U3FTdyt0WkdBPT0tLVFxQ2pxNzIvaXRRNU5wWWMrdHdLS2c9PQ%3D%3D--1967ac769cb1b7ee4f1e8203481f591f8bffea25; path=/; HttpOnly
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: ccd6569c-3004-4ff3-bce2-88b3581d8941
X-Runtime: 0.008415
X-XSS-Protection: 1; mode=block

3. Request Headers

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: max-age=0
Connection: keep-alive
Cookie: _itest5_session=Zzc1WEkzSENiSHp1bSs0blZnMkNlS0l3VndVUXJEbTdiNGlXcmJuRjBsVVNDT080Rkg1V1Y4NFhqUmNVSU5vb2JVZC9VZU5CYnV1K3hBQlMrK21LUFBjdFJiVEo5SnNQQXo5Z0h0YzFIUWNndDI1L2ZhTkRrR0Zvc3REQnRZdTlkSUc1RXRmQjJMSFAxcGlVS1NNZDBnPT0tLS84akN1Mjl2U1dNQWkxRmJPaENjQmc9PQ%3D%3D--add7f6226ae3747a638a65c45a8fd7eecfc0fbce; Hm_lvt_906c6961a45234ebc29e93442b414707=1524100786; Hm_lpvt_906c6961a45234ebc29e93442b414707=1524100786
Host: www.itest.info
If-None-Match: W/"36e8ed1080e1b05a1f5df880fc857d08"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
X-FirePHP-Version: 0.0.6

(四)实战yslow前端性能测试

安装Yslow工具

  • 下载yslow插件(感谢pf04同窗提供yslow插件)
  • 打开chrome://extensions/,直接将插件拖拽过去便可

lpbPz.md.png

对ur.tencent.com前端页面进行测试

  • chrome打开网页ur.tencent.com

  • 点击yslow的扩展程序图标

lpuHh.md.png

  • 点击Run Test

lplS6.md.png

  • 查看测试结果

lsWJR.md.png


(五)HTTP缓存

重用已经获取的资源可以有效的提高网站与应用的性能。Web缓存可以减小延迟与网络阻塞,进而减小显示某个资源所用的时间。借助HTTP缓存,Web站点变得更具备响应性。

总而言之合理使用缓存能够加快站点的响应速度,让用户有页面秒开的快感。

各类各样的缓存

思考一个问题:从硬盘拷贝文件到指定文件夹比较快仍是网络上传下载一样一份文件比较快?——拷贝比较快。

缓存就是尽可能让咱们从本地读取内容(这些内容每每是远程服务器上相应内容的拷贝),从而替代从服务器上读取内容的技术。

缓存是指存储指定资源的一份拷贝,并在下次请求该资源时提供该拷贝的技术。当Web缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不是去源服务器从新下载。这样带来的好处:缓解服务器端压力,提示性能(获取资源的耗时更短)。对于网站来讲,缓存是达到高性能的重要组成部分。缓存须要合理配置,由于并非全部资源都是永久不变的;重要的是对一个资源的缓存应截止到其下一次发生改变(即不能缓存过时资源)。

1. 私有服务器缓存

私有缓存只能用于单独用户。可能已经见过浏览器设置中的“缓存”选项。浏览器缓存拥有用户经过HTTP下载的全部文档。这些缓存为浏览过的文档提供向后/向前导航,保存网页,查看源码等功能,能够避免再次向服务器发起多余的请求。它一样能够提供缓存内容的离线浏览。

2. 共享代理缓存

共享缓存能够被多个用户使用。例如,ISP或你所在的公司可能会架设一个web代理来做为本地网络基础的一部分提供给用户。这样热门的资源就会被重复使用,减小网络拥堵与延迟。

缓存操做的目标

虽然HTTP缓存不是必须的,但重用缓存的资源一般是必要的。然而常见的HTTP缓存只能存储GET响应,对于其余类型的响应则无能为力。缓存的关键主要包括request method和目标URI(通常只有GET请求才会被缓存)。广泛的缓存案例:

  • 一个检索请求的成功响应:状态码为200,一个包含例如HTML文档、图片或者文件的响应
  • 不变的重定向:响应状态码为301
  • 错误响应:响应状态码为206,只返回局部的信息
  • 除了GET请求外,若是匹配到昨晚一个已被定义的cache键名的响应

针对一些特定的请求,也能够经过关键字区分多个存储的不一样响应以组成缓存的内容。

缓存控制

Cache-control Headers

HTTP/1.1定义的Cache-Control头用来区分对缓存机制的支持状况,请求头和响应头都支持这个属性。经过它提供不一样的值来定义缓存策略。

彻底不支持缓存

缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。

不缓存内容

在释放缓存内容前向服务端源地址发送请求以验证缓存释放有效。

私有缓存和公共缓存

  • public: 响应能够被任何请求来源缓存。针对须要进行http身份验证的页面或者一些不能被顺利缓存的响应码,经过定义public以支持缓存。

  • private:响应的内容只能被惟一的用户缓存,不能够被共享缓存存储。隐私模式下的浏览器会经过这种方式存储缓存。

缓存过时

判断缓存释放过时的一个最经常使用的标志为max-age。相对Expires而言,max-age是距离请求发起的时间的秒数。针对应用中那些不会改变的文件,一般能够收到设置必定时长以保证缓存有效,例如图片、css、js等静态资源。

缓存验证

must-revalidate:在使用一些老的资源钱强制验证状态判断是否过时。

Pragma Headers

Pragma是HTTP/1.0标准中定义的一个header属性,请求中包含Pragma的效果跟在头信息中定义Cache-Control:no-cache相同,可是HTTP的响应头不支持这个属性,因此它不能拿来彻底替代HTTP/1.1中定义的Cache-control头。一般定义Pragma以向后兼容基于HTTP/1.0客户端。

缓存有效性

一旦一个资源文件被存入缓存,理论上来讲这个文件就永远处于缓存中。可是缓存的存储空间一般有限,这也意味着按期会移除一部分缓存文件。这个过程被称为缓存抛弃。另外一方面,针对那些在服务端发生改变的资源,应该作响应的缓存内容更新。由于HTTP协议在C-S架构中是无状态的,服务端在资源发生变化时没法通知到客户端,经过定义过时时间以同步两端的缓存资源。在过时时间前,资源缓存是有效的,反正则缓存失效。经过不停抛弃过时的缓存资源以保证资源的实时性。注意,旧的缓存不会被抛弃或者忽略;当发起一个针对旧缓存资源的请求时,会在请求头里带上If-None-Match用来判断缓存是否有效。若是有效,服务端返回304(Not Modified)和空的body以节省一部分带宽。

对于含有特定头信息的请求,会去计算缓存寿命。好比Cache-control:max-age=N的请求头,相应的缓存的寿命就是N。一般状况下,对于不含这个属性的请求则会查看是否包含Expires属性,经过比较Expires的值和头里面Date属性的值来判断是否缓存还有效。若是max-age和expires属性都没有,找找头里面的Last-Modified信息。若是有,缓存的寿命就等于头里面Data的值减去Last-Modified的值除以10。

缓存时长计算公式以下:

缓存时长 = 响应时间 + 缓存寿命 - 当前时间

响应时间指浏览器接收到服务端的响应的时间。

加速资源

更多地利用缓存资源,能够提升网站的性能和相应速度。为了优化缓存,过时时间设置得尽可能长是一种很好的测量。对应按期或者频繁更新的资源,这么作是比较稳妥的,可是对于那些长期不更新的资源会有点儿问题。这些固定的资源在必定时间内受益于这种长期保持的缓存策略,但一旦要更新就会很困难。特指网页上引入的一些js/css文件,当它们变更时须要尽快更新线上资源。

web开发者发明了一种Steve Sounders称做加速的技术。不频繁更新的文件会使用特定的命名方式:在URL后面(一般是文件名后面)会加上版本号。加上版本号后的资源就被视做一个彻底新的独立的资源,同时拥有一年甚至更长的缓存过时时长。可是这么作也存在一个弊端,全部引用这个资源的地方都须要更新连接。web开发者们一般会才有自动化构建工具在实际工做中完成这些琐碎的工做。当低频更新的资源(js/css)变更了,只用在高频变更的资源文件(html)里作入口的改动。

这种方法还有一个好处:同时更新两个缓存资源不会形成部分缓存先更新而引发新旧文件内容不一致。对于互相有依赖关系的css和js文件,避免这种不一致性是很是重要的。

加在加速文件后面的版本号不必定是一个正式的版本号字符串,如1.1.3这样或者其余固定自增的版本数。它能够是任何防止缓存碰撞的标记例如hash或者时间戳。

缓存验证

用户点击刷新按钮时会开始缓存验证。若是缓存的响应头信息里含有“Cache-control:must-revalidate”的定义,在浏览的过程当中也会触发缓存验证。另外,在浏览器偏好设置里设置Advanced-> Cache为强制验证缓存也能达到相同的效果。

当缓存的文档过时后,须要进行缓存验证或者从新获取资源。只有在服务器返回强校验器或者弱校验器时才会进行验证。

ETag

做为缓存的一种强校验器,ETag响应头是一个对用户代理(User Agent,下面简称UA)不可知的值。对于像浏览器这样的HTTP UA,不知道ETag表明什么,值是多少。若是资源请求的响应头里含有ETag,客户端能够在后续的全部请求的头中带上If-None-Match头来验证缓存。

Last-Modified响应头能够做为一种弱校验器。说它弱是由于它是一次性的。若是响应头里含有这个信息,客户端能够在后续的一次请求中带上If-Modified-Since来验证缓存。

当向服务端发起缓存校验的请求时,服务端会返回200 ok表示返回正常的结果或者304 Not Modified(不返回body)表示浏览器可使用本地缓存文件。304的响应头也能够同时更新缓存文档的过时时间。

1. 带Vary头的响应

Vary HTTP响应头决定了对于后续的请求头,如何判断是请求一个新的资源仍是使用缓存的文件。

当缓存服务器收到一个请求,只有当前的请求和原始(缓存)的请求头跟缓存的响应头里的Vary都匹配,才能使用缓存的响应。

使用vary头有利于内容服务的动态多样性。例如,使用Vary:User-Agent头,缓存服务器须要经过UA判断是否使用缓存的页面。若是须要区分移动端和桌面端的展现内容,利用这种方式就能避免在不一样的终端展现错误的布局。另外,它能够帮助google或者其余搜索引擎更好地发现页面的移动版本,而且告诉搜索引擎没有引入Cloaking。

由于移动版和桌面的客户端的请求头中的User-Agent不一样,缓存服务器不会错误地把移动端的内容输出到桌面端用户。

2. max-age

max-age=120s,表示在120s以内,这个请求的内容都是能够从缓存里读取的。

3. ETags

上面的请求120s以后就会过时,这时候若是浏览器再去发送一个请求去获取资源的话,那仍是会蛮浪费的。毕竟资源的内容已经被浏览器缓存下来了。

经过ETags能够解决这个问题。

服务器生成1个ETags,客户端不须要知道这个ETags是如何生成的,在下一个请求发送时,客户端向服务器带上这个ETags,若是没有变化,那么证实内容没变,本次下载能够被忽略。


(六)HTTP请求

HTTP消息是服务器和客户端之间交换数据的方式。有两种类型的消息:

  • 请求 - 由客户端发送用来触发一个服务器上的动做;
  • 响应 - 来着服务器的应答

HTTP请求

** 起始行 **

HTTP请求是由客户端发出的消息,用来使服务器执行动做。起始行(start-line)包含三个元素:

    1. 一个HTTP方法,一个动词(像GET,PUT或者POST)或者一个名词(像HEAD或者OPTIONS),描述要执行的动做。例如,GET表示要获取资源,POST表示向服务器推送数据(建立或修改资源,或者产生要返回的临时文件)。
    1. 请求目标(request target),一般是一个URL,或者是协议、端口和域名的绝对路径,一般以请求的环境为特征。请求的格式因不一样的HTTP方法而异。它能够是:

a. 一个绝对路径,末位跟上一个"?"和查询字符串。这是最多见的形式,称为原始形式(origin form),被GET,POST, HEAD和OPTIONS方法所使用。

b. 一个完整的URL,被称为绝对形式(absolute form),主要在GET链接到代理时使用。

GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1

c. 由郁闷和可选端口(以“:”为前缀)组成的URL的authority component,称为authority form。仅在使用CONNECT创建HTTP隧道时才使用。

CONNECT developer.mozilla.org:80 HTTP/1.1

d. 星号形式(asterisk form),一个简单的星号(/*/),配合OPTIONS方法使用,表明整个服务器。

    1. HTTP版本(HTTP version),定义了剩余报文的结构,做为对指望的响应版本的指示符。

** Headers **

来自请求的HTTP headers遵循和HTTP header相同的基本结构:不区分大小写的字符串,紧跟着的冒号(:)和一个结构取决于header的值。这个header(包括值)由一行组成,这一行能够至关长。

有须要请求头可用,它们能够分为几组:

  • General headers, 例如 Via,适用于整个报文。
  • Request headers, 例如User-Agent, Accept-Type,经过进一步的定义(例如Accept-Language), 或者给定上下文(例如Referer),或者进行有条件的限制(例如If-None)来修改请求。
  • Entity headers,例如Content-Length,适用于请求的body。显然,若是请求中没有任何body,则不会发送这样的头文件。

** Body **

请求的最后一部分是它的body。不是全部的请求都有一个body:例如获取资源的请求,GET,HEAD, DELETE和OPTIONS,一般他们不须要body。有些请求将数据发送到服务器以便更新数据:常见的状况是POST请求(包含HTML表单数据)。

Body大体可分为两类:

  • Singel-resource bodies,由一个单文件组成。该类型body由两个header定义:Content-TypeContent-Length

  • Multiple-resource bodies, 由多部分body组成,每一部分包含不一样的信息位。一般是和HTML Forms连系在一块儿

HTTP响应

** 状态行 **

HTTP响应的起始行被称做状态行(status line),包含如下信息:

    1. 协议版本,一般为HTTP/1.1
    1. 状态码(status code),代表请求是成功或失败。常见的状态码是200,400或302。
    1. 状态文本(status text)。一个简短的,纯粹的信息,同状态码的文本描述,帮助人们理解该HTTP消息

一个典型的状态行看起来像这样的: HTTP/1.1 404 Not Found

** Headers **

响应的HTTP headers遵循和任何其余header相同的结构:不区分大小写的字符串,紧跟着冒号(:)和一个结构取决于header类型的值。整个header(包括其值)表现为单行形式。

有不少响应头可用,这些响应头能够分为几组:

  • General headers,例如Via,适用于整个报文;

  • Response header,例如VaryAccept-Ranges,提供其它不符合状态行的关于服务器的信息;

  • Entity headers,例如Content-Length,适用于请求的body。显然,若是请求中没有任何body,则不会发送这样的头文件。

** Body **
响应的最好一部分是body。不是全部的响应都有body:具备状态码(如201或204)的响应,一般不会有body。

body大体可分为三类:

  • Single-resource bodies, 由已知长度的单个文件组成。该类型的body由两个header定义:Content-Type和Content-Length。

  • Single-resource bodies,由未知长度的单个文件组成,经过将Transfer-Encoding设置为chunked 来使用chunks编码。

  • Multiple-resource bodies,由多部分body组成,每部分包含不一样的信息段。但这是比较少见的。


HTTP Cookie(也叫Web cookie或者浏览器Cookie)是服务器发送到用户浏览器并保存在浏览器上的一块数据,它会在浏览器下一次发起请求时被携带并发送到服务器上。比较经典的,能够用来肯定两次请求是否来自同一个浏览器,从而可以确认和保持用户的登陆状态。Cookie的使用是的基于无状态的HTTP协议记录稳定的状态信息成为了可能。

  • 会话状态管理(如用户登陆状态、购物车)
  • 个性化设置(如用户自定义设置)
  • 浏览器行为跟踪(如跟踪分析用户行为)

Cookie可用于客户端数据的存储,在没有其余存储办法时,使用这种方式是可行的,但随着如今浏览器开始支持各类各样的存储方式而逐渐被废弃。因为服务器指定Cookie之后浏览器的每次请求都会携带Cookie数据,这会带来额外的性能负担(尤为是在移动环境下)。新的浏览器API已经容许开发者直接在本地存储数据,如可使用Web storage API(本地存储和会话存储)和IndexedDB。

建立cookie

当服务器收到HTTP请求时,能够在响应头里面增长一个Set-Cookie头部。浏览器收到响应以后会取出Cookie信息并保存,以后对该服务器每一次请求中都经过Cookie请求头部将Cookie信息发送给服务器。另外,Cookie的过时时间、域、路径、有效期、站点均可以根据须要来指定。

Set-Cookie响应头部和Cookie请求头部

服务器使用Set-Cookie响应头部向用户代理(通常指浏览器)发送Cookie信息。一个简单的Cookie可能像这样: Set-Cookie: <cookie名称> = <cookie值>

服务器告诉客户端要保存Cookie信息(服务端程序能够是PHP、Node.js、Python或者Ruby on Rails等语言所写),响应的数据里面应该包含Set-Cookie头,浏览器收到以后会降Cookie保存。

对该服务器发起的每一次显得呃请求,浏览器都会将以前保存的Cookie信息经过Cookie请求头发送给服务器。

会话期Cookie

会话期Cookie是最简单的Cookie:浏览器关闭以后它会被自动删除,也就是它仅在会话期间有效。会话期Cookie不须要指定过时时间(Expires)或者有效期(Max-Age)。须要注意的是,有效浏览器提供了会话恢复的功能,这种状况下即便关闭了浏览器会话期Cookie也会被保存,就好像浏览器历来没有关闭同样。

持久Cookie

和关闭浏览器便失效不一样,持久Cookie能够指定一个特定的过时时间(Expires)或者有效期(Max-Age)

Set-Cookie: id=a3fWa;Expires=Web, 21 Oct 2015 07:28:00 GMT;

安全和HttpOnly类型Cookie

只有在使用SLL和HTTPS协议向服务器发起请求时,才能确保Cookie被安全地发送到服务器。HttpOnly标志并无给你提过额外的加密或者安全性上的能力,当整个机器暴露在不安全的环境时,切记毫不能经过HTTP Cookie存储、传输机密或者敏感信息。

HTTP-only类型的Cookie不能使用Javascript经过Document.cookie属性来访问,从而可以在必定程度上阻止跨域脚本攻击(XSS)。当你不须要在JavaScript代码中访问你的Cookie时,能够将该Cookie设置成HttpOnly类型。特别地,当你的Cookie仅仅是用于定义会话的状况下,最好给它设置一下HttpOnly标志。

Cookie的做用域

Domain和Path指令定义了Cookie的做用域,即须要发送Cookie的URL集合。

Domain指令规定了须要发送Cookie的主机名。若是没有指定,默认为当前的文档地址上的主机名(可是不包含子域名)。若是指定了Domain,则通常包含子域名。

若是设置了Domain=mozilla.org,则Cookie包含在子域名中(如developer.mozilla.org)。

Path指令代表须要发送Cookie的URL路径。字符%x2F(即“/”)用做文件夹分隔符,子文件夹也会被匹配到。

同站Cookie

同站Cookie容许服务器指定在跨站请求时Cookie是否会被发送,从而能够阻止跨站请求伪造攻击(CSRF)。


安全

当整个机器暴露在不安全的环境时,切记毫不能经过HTTP Cookie存储、传输机密或者敏感信息。

会话挟持和XSS

在Web应用中,Cookie经常用例标记用户和会话受权。所以,若是窃取了Web应用的Cookie,可能致使受权用户的会话受到攻击(能够能会致使攻击者得到用户的身份)。经常使用的窃取Cookie的方法有利用社会工程学进行攻击和利用应用程序的漏洞进行XSS攻击。

HttpOnly类型的Cookie因为阻止了JavaScript对Cookie进行访问而能在必定程度上环境此类攻击。

跨站请求伪造(CSRF)

维基百科有一个比较好的CSRF的例子:有一张并不真实存在的图片(多是在不安全聊天室或论坛),其实是向你的银行服务器发送了提现请求。

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">

当你打开含有这张图片的HTML页面是,若是你已经等了了你的银行帐户而且还有效(并且没有其余验证步骤),你的银行里的钱可能会被自动转走。这里有一些方法能够阻止该类事情的发生:

  • 对用户输入进行过滤来阻止XSS;
  • 任何敏感的操做都应该来确认;
  • 用于敏感信息的Cookie只能拥有较短的生命周期;

追踪和隐私

1.第三方Cookie

每一个Cookie都有与之关联的域(Domain),若是Cookie的域和页面的域是同样的,那么称为这个Cookie为第一方Cookie,若是Cookie的域和页面的域不同,则称之为第三方Cookie。大多数浏览器默认状况下都容许第三方Cookie,可是能够经过附加组件来阻止第三方Cookie。

2.僵尸Cookie和删不掉的Cookie

Cookie的一个极端使用例子是僵尸Cookie(也称为删不掉的Cookie)。这类Cookie较难以删除,甚至删除以后会自动重现。