这里我只是对一些知识进行简单的整理,方便自己理解记忆,还有很多不完善的地方,更多细节,需要查看书籍或者其他文章
http 协议的发展过程
HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用 80 端口。
http/0.91991 年发布,只有一个命令 GET,协议规定,服务器只能回应 HTML 格式的字符串,不能回应别的格式。
http/1.01996 年 5 月发布,HTTP/1.0 版本发布,内容大大增加,首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。除了 GET 命令,还引入了 POST 命令和 HEAD 命令,丰富了浏览器与服务器的互动手段。
HTTP 请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
** 缺点:**
每个 TCP 连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。TCP 连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0 版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。为了解决这个问题,有些浏览器在请求时,用
列表项目
了一个非标准的 Connection 字段。
Connection: keep-alive
一个可以复用的 TCP 连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。
http/1.11997 年 1 月发布,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了 20 年后的今天,直到现在还是最流行的版本。
1.1 版的最大变化,就是引入了持久连接(persistent connection),即 TCP 连接默认不关闭,可以被多个请求复用,不用声明 Connection: keep-alive。
客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送 Connection: close,明确要求服务器关闭 TCP 连接。
1.1 版还新增了许多动词方法:PUT、PATCH、HEAD、OPTIONS、DELETE。
** 缺点 **
虽然 1.1 版允许复用 TCP 连接,但是同一个 TCP 连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为 ” 队头堵塞 ”(Head-of-line blocking)。为了避免这个问题,只有两种方法:一是减少请求数;二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入 CSS 代码、域名分片(domain sharding)等等。如果 HTTP 协议设计得更好一些,这些额外的工作是可以避免的。
SPDY2009 年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。这个协议在 Chrome 浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。
HTTP/22015 年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。
HTTP/1.1 版的头信息肯定是文本(ASCII 编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议。
二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
HTTP/2 复用 TCP 连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了 ” 队头堵塞 ”。
HTTPSHTTPS 是 HTTP 协议的安全版本,HTTP 协议的数据传输是明文的,是不安全的,HTTPS 使用了 SSL/TLS 协议进行了加密处理。
http 协议的特点
无状态——每次 HTTP 请求都是独立的,任何两个请求之间没有什么必然的联系。但是在实际应用当中并不是完全这样的,引入了 Cookie 和 Session 机制来关联请求。
无连接的——每次请求完成之后立即断开连接
单向的应用层协议——通信请求只能由客户端发起,服务端对请求做出应答处理。
多次请求—— 在客户端请求网页时多数情况下并不是一次请求就能成功的,服务端首先是响应 HTML 页面,然后浏览器收到响应之后发现 HTML 页面还引用了其他的资源,例如,CSS,JS 文件,图片等等,还会自动发送 HTTP 请求这些需要的资源。
现在的 HTTP 版本支持管道机制(即在同一个 TCP 连接里面,客户端可以同时发送多个请求),可以同时请求和响应多个请求,大大提高了效率。
http 报文结构
请求行
url —— Request URL
请求方法 —— Request Method
状态码 —— Status Code
服务器地址 —— Remote Address 在跨域拒绝时,可能是 method 为 options,状态码为 404/405 等(当然,实际上可能的组合有很多)的
** 常用状态码:**
200——表明该请求被成功地完成,所请求的资源发送回客户端
304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
400——客户端请求有错(譬如可以是安全模块拦截)
401——请求未经授权
403——禁止访问(譬如可以是未登录时禁止)
404——资源未找到
500——服务器内部错误
503——服务不可用
…
**HTTP 请求方法 **
在 HTTP1.1 版本中支持 GET、POST 等近 10 种方法.
通用首部字段
HTTP Cookie
本质上 cookies 就是 http 的一个扩展。有两个 http 头部是专门负责设置以及发送 cookie 的, 它们分别是 Set-Cookie 以及 Cookie。
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。
Cookie 主要用于以下三个方面:
会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
个性化设置(如用户自定义设置、主题等)
浏览器行为跟踪(如跟踪分析用户行为等)
Cookie 曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。由于服务器指定 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(本地存储和会话存储)或 IndexedDB。
创建 cookie 服务器收到 HTTP 请求时,服务器可以在响应头里面添加一个 Set-Cookie 选项。浏览器收到响应后通常会保存下 Cookie,之后对该服务器每一次请求中都通过 Cookie 请求头部将 Cookie 信息发送给服务器。另外,Cookie 的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。
nodejs 中服务端设置 cookie 的方法
request.setHeader(‘Set-Cookie’, [‘type=ninja’, ‘language=javascript’]);
cookie 是保存在客户端中,按照客户端中存储的位置,可分为内存 cookie 和硬盘 cookie。
内存 cookiecookie 的生存时间是整个会话期间的话,浏览器会将 cookie 保存在内存中,浏览器关闭时就会自动清除这个 cookie
硬盘 cookie 就是 cookie 保存在客户端的硬盘中,浏览器关闭的话,该 cookie 也不会被清除,下次打开浏览器访问对应网站时,这个 cookie 就会自动再次发送到服务器端。
cookie 不可跨域很多网站都会使用 Cookie。例如:Google 会向客户端颁发 Cookie,Baidu 也会向客户端颁发 Cookie。那浏览器访问 Google 会不会也携带上 Baidu 颁发的 Cookie 呢?或者 Google 能不能修改 Baidu 颁发的 Cookie 呢?案是否定的。Cookie 具有不可跨域名性。根据 Cookie 规范,浏览器访问 Google 只会携带 Google 的 Cookie,而不会携带 Baidu 的 Cookie。Google 也只能操作 Google 的 Cookie,而不能操作百度的 Cookie。Cookie 在客户端是由浏览器来管理的。浏览器能够保证 Google 只会操作 Google 的 Cookie 而不会操作 Baidu 的 Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站 Cookie 的依据是域名。Google 与 Baidu 的域名不一样,因此 Google 不能操作 Baidu 的 Cookie。
同一个一级域名下的两个二级域名如 www.helloweenvsfei.com 和 images.helloweenvsfei.com 也不能交互使用 Cookie,因为二者的域名并不严格相同。如果想所有 helloweenvsfei.com 名下的二级域名都可以使用该 Cookie,需要设置 Cookie 的 domain 参数,例如:
Cookie cookie = new Cookie(“time”,”20080808″); // 新建 Cookie
cookie.setDomain(“.helloweenvsfei.com”); // 设置域名
cookie.setPath(“/”); // 设置路径
cookie.setMaxAge(Integer.MAX_VALUE); // 设置有效期
response.addCookie(cookie); // 输出到客户端
cookie 的有效期 Cookie 的 maxAge 决定着 Cookie 的有效期,单位为秒(Second)。Cookie 中通过 getMaxAge() 方法与 setMaxAge(int maxAge) 方法来读写 maxAge 属性。如果 maxAge 属性为正数,则表示该 Cookie 会在 maxAge 秒之后自动失效。浏览器会将 maxAge 为正数的 Cookie 持久化,即写到对应的 Cookie 文件中。无论客户关闭了浏览器还是电脑,只要还在 maxAge 秒之前,登录网站时该 Cookie 仍然有效。
如果 maxAge 为负数,则表示该 Cookie 仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该 Cookie 即失效。maxAge 为负数的 Cookie,为临时性 Cookie,不会被持久化,不会被写到 Cookie 文件中。Cookie 信息保存在浏览器内存中,因此关闭浏览器该 Cookie 就消失了。
注意:从客户端读取 Cookie 时,包括 maxAge 在内的其他属性都是不可读的,也不会被提交。浏览器提交 Cookie 时只会提交 name 与 value 属性。maxAge 属性只被浏览器用来判断 Cookie 是否过期。
Cookie 的安全属性 HTTP 协议不仅是无状态的,而且是不安全的。使用 HTTP 协议的数据不经过任何加密就直接在网络上传播,有被截获的可能。使用 HTTP 协议传输很机密的内容是一种隐患。如果不希望 Cookie 在 HTTP 等非安全协议中传输,可以设置 Cookie 的 secure 属性为 true。浏览器只会在 HTTPS 和 SSL 等安全协议中传输此类 Cookie。下面的代码设置 secure 属性为 true:
Cookie cookie = new Cookie(“time”, “20080808”); // 新建 Cookie
cookie.setSecure(true); // 设置安全属性
response.addCookie(cookie); // 输出到客户端
提示:secure 属性并不能对 Cookie 内容加密,因而不能保证绝对的安全性。如果需要高安全性,需要在程序中对 Cookie 内容加密、解密,以防泄密。
http session
session 和 cookie 一样,都是用来记录 http 状态的一种机制,但不同的是 cookie 存在于客户端,所携带的大小收到限制,而 session 则存在于服务端,存储的大小不受限制。
当程序需要为某个客户端的请求创建一个 session 的时候,服务器首先检查这个客户端的请求里是否已包含了一个 session 标识 - 称为 session id,如果已包含一个 session id 则说明以前已经为此客户端创建过 session,服务器就按照 session id 把这个 session 检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含 session id,则为此客户端创建一个 session 并且生成一个与此 session 相关联的 session id,session id 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id 将被在本次响应中返回给客户端保存。保存这个 session id 的方式可以采用 cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个 cookie 的名字都是类似于 SEEESIONID。
通常 session 的创建需要依赖 cookie,但 cookie 可以被人为的禁止,需要有其他的机制以便在 cookie 被禁止的时候能够把 session id 传递回服务器,可以把 session id 直接附加在 URL 路径的后面
注意:在谈论 session 机制的时候,常常听到这样一种误解“只要关闭浏览器,session 就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对 session 来说也是一样的,除非程序通知服务器删除一个 session,否则服务器会一直保留,程序一般都是在用户做 log off 的时候发个指令去删除 session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分 session 机制都使用会话 cookie 来保存 session id,而关闭浏览器后这个 session id 就消失了,再次连接服务器时也就无法找到原来的 session。如果服务器设置的 cookie 被保存到硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 session id 发送给服务器,则再次打开浏览器仍然能够找到原来的 session。
参考文章:http://www.ruanyifeng.com/blo…https://www.cnblogs.com/wxism…https://developer.mozilla.org…https://www.2cto.com/kf/20120…