这篇文章主要是我平时在学习HTTP过程当中看到的一些知识点,如今把他们总结成一篇文章,创建一个本身的知识体系,全是干货。另外,推荐一本很是棒的HTTP书——《图解HTTP》,这本书图文并茂,挺有趣的。
javascript
HTTP是基于TCP/IP协议的应用层协议,用于客户端和服务器之间的通讯,默认80端口。咱们按照他的发展历程的时间顺序开始说。css
1990年提出的,是最先期的版本,只有一个命令GET。html
1996年5月提出的。html5
缺点
:每一个TCP链接只能发送一个请求。解决方法
:Connection:keep-alive 1997年1月提出,如今使用最普遍的。java
长链接
:TCP链接默认不关闭,能够被多个请求复用。对于同一个域名,大多数浏览器容许同时创建6个持久链接。默认开启Connection:keep-alive。
jquery
管道机制
:在同一个TCP链接里,能够同时发送多个请求。可是服务器仍是要按照请求的顺序进行响应,会形成“队头阻塞”。
web
HTTP首部分为请求报文和响应报文。它们的格式以下所示:
ajax
其中首部字段又分为不少种,咱们先看通用首部字段,这是请求报文和响应报文种都会使用的首部。数据库
一、Cache-Control
:操做缓存的工做机制
json
参数:
- public:明确代表其余用户也能够利用缓存
- private:缓存只给特定的用户
- no-cache:客户端发送这个指令,表示客户端不接收缓存过的响应,必须到服务器取;服务器返回这个指令,指缓存服务器不能对资源进行缓存。实际上是不缓存过时资源,要向服务器进行有效期确认后再处理资源。
- no-store:指不进行缓存
- max-age:缓存的有效时间(相对时间)
二、Connection
:
- Connection:keep-Alive (持久链接)
- Connection:再也不转发的首部字段名
三、Date
:代表建立http报文的日期和时间
四、Pragma
:兼容http1.0,与Cache-Control:no-cache含义同样。但只用在客户端发送的请求中,告诉全部的中间服务器不返回缓存。形式惟一:Pragma:no-cache
五、Trailer
:会事先说明在报文主体后记录了哪些首部字段,该首部字段能够应用在http1.1版本分块传输编码中。
六、Transfer-Encoding
:chunked (分块传输编码), 规定传输报文主体时采用的编码方式,http1.1的传输编码方式只对分块传输编码有效
七、Upgrade
:升级一个成其余的协议,须要额外指定Connection:Upgrade。服务器可用101状态码做为相应返回。
八、Via
:追踪客户端和服务器之间的请求和响应报文的传输路径。能够避免请求回环发生,因此在通过代理时必需要附加这个字段。
一、Accept:通知服务器,用户代理可以处理的媒体类型及媒体类型的相对优先级 q表示优先级的权重值,默认为q = 1.0,范围是0~1(可精确到小数点后3位,1为最大值) 当服务器提供多种内容时,会先返回权重值最高的媒体类型
二、Accept-Charset:支持的字符集及字符集的相对优先顺序,跟Accept同样,用q来表示相对优先级。这个字段应用于内容协商机制的服务器驱动协商。
三、Accept-Encoding:支持的内容编码及内容编码的优先级顺序,q表示相对优先级。 内容编码:gzip、compress、deflate、identity(不执行压缩或者不会变化的默认编码格式)。 可使用*做为通配符,指定任意的编码格式。
四、Accept-Language:可以处理的天然语言集,以及相对优先级。
101 协议升级
,主要用于升级到websocket,也能够用于http2
200 OK
204 No content
,服务器成功处理请求,可是返回的响应报文中不含实体的主体部分
206 Partial Content
,表示客户端像服务器进行了范围请求(Content-Range字段),服务器成功返回指定范围的实体内容
301 永久性重定向
,表示请求的资源已经被分配了新的url,旧地址之后都不能再访问了,服务器会返回location字段,包含的是新的地址。
302 临时性重定向
,表示请求的资源临时移动到一个新地址
注意:尽可能使用301跳转,由于302会形成网址劫持,可能被搜索引擎判为可疑转向,甚至认为是做弊。
缘由:从网站A(网站比较烂)上作了一个302跳转到网站B(搜索排名很靠前),这时候有时搜索引擎会使用网站B的内容,但却收录了网站A的地址,这样在不知不觉间,网站B在为网站A做贡献,网站A的排名就靠前了。
303 See Other
,与302功能相同,可是它明确规定客户端应采用GET方法获取资源
304 未修改
,协商缓存中返回的状态码
307 临时重定向
,与302功能相同,但规定不能从POST变成GET
当30一、30二、303响应状态码返回时,几乎全部浏览器都会把post改为get,并删除请求报文内的主体,以后请求会自动再次发送。然而30一、302标准是禁止将post方法改变成get方法的,但实际使用时你们都会这么作。因此须要307。
400 Bad Request
,表示请求报文中存在语法错误。当错误发生时,须要修改请求的内容再次发送请求
401 unauthorized
,表示发送的请求须要有经过HTTP认证(BASIC认证、DIGEST认证)的认证信息。若是以前已经进行过一次请求,表示用户认证失败。
403 禁止
,表示拒绝对请求资源的访问
404 Not Found
,代表服务器上没法找到请求的资源
500 Internet Server Error
,该状态码表示服务器在执行请求时发生了错误
500 Service Unavailable
,表示服务器暂时处于超负荷或者处于停机维护状态,如今没法处理请求
2009年谷歌提出。
SPDY结构
:新增特性
:缺点
:html5新提出来的,是web浏览器与web服务器之间的全双工通讯标准。主要是为了解决ajax和comet里的xmlhttprequest附带的缺陷所引发的问题。
(1)推送功能:服务器可直接发送数据,不须要等待客户端的请求;
(2)基于TCP传输协议,并复用HTTP的握手通道;
(3)支持双向通讯,用于实时传输消息;
(4)更好的二进制支持;
(5)更灵活,更高效。
一、客户端:发起协议升级请求
GET / HTTP/1.1 `采用HTTP报文格式,只支持get请求`
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade `表示要升级协议`
Upgrade: websocket `表示升级到websocket协议`
Sec-WebSocket-Version: 13 `表示websocket 的版本`
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw== `是一个 Base64 encode 的值,是浏览器随机生成的`
Sec-WebSocket-Protocol:chat, superchat `用来指定一个特定的子协议,一旦这个字段有设置,那么服务器须要在创建链接的响应头中包含一样的字段,内容就是选择的子协议之一。`
复制代码
二、服务端:响应协议升级
HTTP/1.1 101 Switching Protocols `101表示协议切换==`
Connection:Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU= `通过服务器确认,而且加密事后的 Sec-WebSocket-Key`
Sec-WebSocket-Protocol:chat `表示最终使用的协议`
复制代码
Sec-WebSocket-Key 的加密过程为:
- 将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
- 经过SHA1计算出摘要,并转成base64字符串。
三、双方握手成功后,就是全双工的通讯了,接下来就是用websocket协议来进行通讯了。
一、ajax轮询
让浏览器每隔必定的时间就发送一次请求,询问服务器是否有新信息。
二、长轮询(Long Poll)
采用的阻塞模式。客户端发起链接后,若是没消息,服务器不会立刻告诉你没消息,而是将这个请求挂起(pending),直到有消息才返回。返回完成或者客户端主动断开后,客户端再次创建链接,周而复始。Comet就是采用的长轮询。
三、websocket
WebSocket 是相似 Socket 的TCP长链接通信模式。一旦 WebSocket 链接创建后,后续数据都以帧序列的形式传输。并且浏览器和服务器就能够随时主动发送消息给对方,是全双工通讯。
优势:在海量并发及客户端与服务器交互负载流量大的状况下,极大的节省了网络带宽资源的消耗,有明显的性能优点,且客户端发送和接受消息是在同一个持久链接上发起,实时性优点明显。
2015年发布,它是基于SPDY的,如下是它的一些新特性:
一、 二进制分帧
:
http/1.x 是一个超文本协议,而 http2 是一个二进制协议,被称之为二进制分帧。 二进制格式在协议的解析和优化扩展上带来更多的优点和可能。
协议格式为帧,帧由 Frame Header(头信息帧)和 Frame Payload(数据帧)组成,以下所示:
二、头部压缩 HPACK
:
请求和响应首部压缩,客户端和服务端共同维护一张头信息表,全部字段存入这个表,生成一个索引号,经过发送索引号提升速度。HPACK压缩会通过两步:
- 传输的value,会通过一遍Huffman coding来节省资源;
- 为了server和client同步, 两边都须要保留一份Header list, 而且,每次发送请求时,都会检查更新。
三、服务端推送
:
服务端主动向客户端推送数据。若是客户端请求一个html文件,服务端把html文件返回给客户端以后,还会相应的把html文件中的js、css、图片推送给客户端。
四、多路复用
:
只须要创建一个TCP链接,浏览器和服务器能够同时发送多个请求或者回应,并且不须要按照顺序一一对应,避免了“队头阻塞”。
五、数据流
:
当客户端同时向服务端发起多个请求,那么这些请求会被分解成一一个的帧,每一个帧都会在一个 TCP 链路中无序的传输,同一个请求的帧的 Stream Identifier 都是同样的。当帧到达服务端以后,就能够根据 Stream Identifier 来从新组合获得完整的请求。
而且规定:客户端发出的数据流ID为奇数,服务器发出的ID为偶数。Stream Identifier (数据流ID)就是用来标识该帧属于哪一个请求的。
HTTPS = HTTP+加密+认证+完整性保护
它的加密过程是:
下图是加密过程的图解,能够对照着图片理一遍。
HTTP的缓存分为强缓存和协商缓存(对比缓存)。
强制缓存
在缓存数据未失效的状况下,能够直接使用缓存数据;在没有缓存数据的时候,浏览器向服务器请求数据时,服务器会将数据和缓存规则一并返回,缓存规则信息包含在响应header中。
Expires:缓存过时时间(HTTP1.0)
缺点:生成的是绝对时间,可是客户端时间能够随意修改,会致使偏差。
Cache-Control :HTTP1.1,优先级高于Expires
可设置参数:
private: 客户端能够缓存
public: 客户端和代理服务器均可缓存
max-age=xxx: 缓存的内容将在 xxx 秒后失效
no-cache: 须要使用协商缓存来验证缓存数据(后面介绍)
no-store: 全部内容都不会缓存,强制缓存,对比缓存都不会触发
Expires和Cache-Control决定了浏览器是否要发送请求到服务器,ETag和Last-Modified决定了服务器是要返回304+空内容仍是新的资源文件。
协商缓存
浏览器第一次请求数据时,服务器会将缓存标识与数据一块儿返回给客户端,客户端将两者备份至缓存数据库中。再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可使用缓存数据。
Last-Modified
:服务器在响应请求时,告诉浏览器资源的最后修改时间。If-Modified-Since
:再次请求服务器时,经过此字段通知服务器上次请求时,服务器返回的资源最后修改时间。
缺点:Last-Modified 标注的最后修改时间只能精确到秒,若是有些资源在一秒以内被屡次修改的话,他就不能准确标注文件的新鲜度了。若是某些资源会被按期生成,当内容没有变化,但 Last-Modified 却改变了,致使文件没使用缓存有可能存在服务器没有准确获取资源修改时间,或者与代理服务器时间不一致的情形。
Etag
:给资源计算得出的一个惟一标志符。If-None-Match
:再次请求服务器时,经过此字段通知服务器客户端缓存数据的惟一标识。
具体过程以下图:
解决http的无状态问题,是客户端保存用户信息的一种机制,用来记录用户的一些信息,来实现session的跟踪。
name、value
:以key/value的形式存在
comment
:说明该cookie的用处
domain
:能够访问该cookie的域名
Expires/maxAge
:cookie失效时间。负数:临时cookie,关闭浏览器就失效;0:表示删除cookie,默认为-1
path
:能够访问此cookie的页面路径
size
:cookie的大小
secure
:是否以https协议传输
version
:该cookie使用的版本号,0遵循Netscape规范,大多数用这种,1遵循W3C规范
HttpOnly
:此属性为true,则只有在http请求头中会带有此cookie的信息,而不能经过document.cookie来访问此cookie,能防止XSS攻击。
客户端请求服务器时,若是服务器须要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。而客户端浏览器会把Cookie保存起来。当浏览器再请求服务器时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器经过检查该Cookie来获取用户状态。
cookie的同源是域名相同,忽略协议和端口,不可跨域。
session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据能够保存在集群、数据库、文件中。
session的运行依赖session id,而session id是存在cookie中的
session机制原理:
当客户端请求建立一个session的时候,服务器会先检查这个客户端的请求里是否已包含了一个session标识——sessionId。若是已包含这个sessionId,则说明之前已经为此客户端建立过session,服务器就按照sessionId把这个session检索出来使用(若是检索不到,可能会新建一个。若是客户端请求不包含sessionId,则为此客户端建立一个session而且生成一个与此session相关联的sessionId。
使用URL重写技术来进行会话跟踪。在 url 中传递 session id,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
cookie 数据存放在客户的浏览器上,session数据放在服务器上;
cookie 不是很安全,别人能够分析存放在本地的 cookie 并进行 cookie 欺骗考虑到安全应当使用 session;
session 会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用 cookie;
单个cookie保存的数据不能超过4K,不少浏览器都限制一个站点最多保存20个 cookie。
鉴于上述区别咱们建议:
(1)将登录信息等重要信息存放为 session;
(2)其余信息若是须要保留,能够放在 cookie 中。
共同点:都是保存在浏览器端、且同源的。
数据存储方面
存储数据大小
数据存储有效期
做用域不一样
跨域产生的缘由,是由于受到同源策略的限制。同源策略指的是协议、域名、端口不相同。这里我将介绍三种跨域的方式:JSONP、CORS(跨域资源共享)、document.domain + iframe。
1. 原理
动态插入script标签(由于script标签不受同源策略的限制),经过插入script标签引入一个js文件,这个js文件加载成功以后会执行咱们在url中指定的回调函数,而且会把咱们须要的json数据做为参数传入。
2. 实现
(1)原生实现:
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// 回调函数
function onBack(res) {
alert(JSON.stringify(res));
}
//服务端返回以下(返回时即执行全局函数):
onBack({"status": true, "user": "admin"})
复制代码
(2)jquery ajax:
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});
复制代码
1. 原理
服务器在响应头中设置相应的选项,浏览器若是支持这种方法的话就会将这种跨站资源请求视为合法,进而获取资源。
2. 实现
CORS分为简单请求和复杂请求,简单请求指的是:
(1)请求方法是如下三种方法之一:HEAD、GET、POST;
(2)HTTP的头信息不超出如下几种字段: Accept、Accept-Language、Content-Language、Last-Event-ID、 Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)。
其余状况就是非简单请求了。
(1)请求头
:
Origin: http://www.domain.com
复制代码
(2)响应头
:
Access-Control-Allow-Origin: http://www.domain.com
Access-Control-Allow-Credentials: true `是否容许传送cookie`
Access-Control-Expose-Headers: FooBar `CORS请求时,只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其余字段,就必须指定。`
复制代码
(3)另外,ajax请求中
,若是要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名,还要设置如下内容:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
复制代码
(1)预检请求
:
OPTIONS /cors HTTP/1.1 `OPTIONS请求是用来询问的`
Origin: http://www.domian.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
复制代码
(2)响应头
:
Access-Control-Allow-Origin: http://www.domain.com
Access-Control-Allow-Methods: GET, POST, PUT `服务器支持的全部跨域请求的方法`
Access-Control-Allow-Headers: X-Custom-Header `服务器支持的全部头信息字段,不限于浏览器在"预检"中请求的字段。`
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000 `指定本次预检请求的有效期,单位为秒`
复制代码
(3)以后的步骤就同简单请求了
。
这是CORS的整个流程图:
与JSOP的比较:
JSONP只支持GET请求,CORS支持全部类型的HTTP请求。JSONP的优点在于支持老式浏览器,以及能够向不支持CORS的网站请求数据。
复制代码
此方案仅限主域相同,子域不一样的跨域应用场景。
1.原理
两个页面都经过js强制设置document.domain为基础主域,就实现了同域。
2.实现
(1)父窗口:(www.domain.com/a.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>
复制代码
(2)子窗口:(child.domain.com/b.html)
<script>
document.domain = 'domain.com';
// 获取父窗口中变量
alert('get js data from parent ---> ' + window.parent.user);
</script>
复制代码