📌Network📌HTTP.txt
超文本传输协议(HTTP)是一个用于传输超媒体文档(例如HTML)的应用层协议。
它是在Web上进行数据交换的基础,是一种client-server协议。
通过TCP,或者是TLS(加密的TCP连接)来发送,理论上任何可靠的传输协议都可以使用。
HTTP是无状态协议,这意味着服务器不会在两个请求之间保留任何数据(状态)。
由像浏览器这样的客户端发出的消息叫做requests,被服务端响应的消息叫做responses。

HTTP定义了一组请求方法,以表明要对给定资源执行的操作。指示针对给定资源要执行的期望动作。
	GET方法请求一个指定资源的表示形式,使用GET的请求应该只被用于获取数据。
	HEAD方法请求一个与GET请求的响应相同的响应,但没有响应体。
	POST方法用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用。
	PUT方法用请求有效载荷替换目标资源的所有当前表示。
	DELETE方法删除指定的资源。
	CONNECT方法建立一个到由目标资源标识的服务器的隧道。
	OPTIONS方法用于描述目标资源的通信选项。
	TRACE方法沿着到目标资源的路径执行一个消息环回测试。
	PATCH方法用于对资源应用部分修改。

HTTP消息头允许客户端和服务器通过request和response传递附加信息。
一个请求头由名称(不区分大小写)后跟一个冒号“:”,冒号后跟具体的值(不带换行符)组成。该值前面的引导空白会被忽略。
自定专用消息头可通过'X-'前缀来添加;但是这种用法被IETF在2012年6月发布的RFC6648中明确弃用,原因是其会在非标准字段成为标准时造成不便。
根据不同上下文,可将消息头分为:
	General headers: 同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。
	Request headers: 包含更多有关要获取的资源或客户端本身信息的消息头。
	Response headers: 包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头。
	Entity headers: 包含有关实体主体的更多信息,比如主体长(Content-Length)度或其MIME类型。

HTTP并不需要其底层的传输层协议是面向连接的,只需要它是可靠的,或不丢失消息的(至少返回错误)。
在互联网中,有两个最常用的传输层协议:TCP是可靠的,而UDP不是。
因此,HTTP依赖于面向连接的TCP进行消息传递,但连接并不是必须的。

在客户端与服务器能够交互之前,必须在这两者间建立一个TCP链接,打开一个TCP连接需要多次往返交换消息(因此耗时)。
HTTP/1.0默认为每一对HTTP请求/响应都打开一个单独的TCP连接。
当需要连续发起多个请求时,这种模式比多个请求共享同一个TCP链接更低效。
HTTP/2则通过在一个连接复用消息的方式来让这个连接始终保持为暖连接。 

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。
当web缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。
这样带来的好处有:缓解服务器端压力,提升性能(获取资源的耗时更短了)。
对一个资源的缓存应截止到其下一次发生改变(即不能缓存过期的资源)。

缓存的种类有很多,其大致可归为两类:私有与共享缓存。
共享缓存存储的响应能够被多个用户使用。私有缓存只能用于单独用户。
虽然HTTP缓存不是必须的,但重用缓存的资源通常是必要的。
然而常见的HTTP缓存只能存储GET响应,对于其他类型的响应则无能为力。

HTTP/1.1定义的Cache-Control头用来区分对缓存机制的支持情况,请求头和响应头都支持这个属性。
	缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。
	Cache-Control: no-store
	请求带有与本地缓存相关的验证字段,服务器端会验证请求中所描述的缓存是否过期,若未过期才使用本地缓存副本。
	Cache-Control: no-cache
	"public" 指令表示该响应可以被任何中间人(比如中间代理、CDN等)缓存。
	Cache-Control: public
	而"private"则表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。
	Cache-Control: private
	过期机制中,最重要的指令是 "max-age=<seconds>",表示资源能够被缓存的最大时间。
	Cache-Control: max-age=31536000
	当使用了"must-revalidate"指令,那就意味着缓存在考虑使用一个陈旧的资源时,必须先验证它的状态,已过期的缓存将不被使用。
	Cache-Control: must-revalidate

出于安全性,浏览器限制脚本内发起的跨源HTTP请求。
这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。
跨源资源共享标准新增了一组HTTP头字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。

Access-Control-Allow-Origin: <origin> | *
其中,origin参数的值指定了允许访问该资源的外域 URI。
对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。

Access-Control-Expose-Headers: <headers1>[, <headers2>]
让服务器把允许浏览器访问的头放入白名单。这样浏览器就能够通过getResponseHeader访问指定响应头了。

Access-Control-Max-Age: <delta-seconds>
指定了preflight请求的结果能够被缓存多久。

Access-Control-Allow-Credentials: true
当浏览器的credentials设置为true时是否允许浏览器读取response的内容。
当用在对preflight预检测请求的响应中时,它指定了实际的请求是否可以使用credentials。

Access-Control-Allow-Methods: <method>[, <method>]*
预检请求的响应。其指明了实际请求所允许使用的HTTP方法。

Access-Control-Allow-Headers: <field-name>[, <field-name>]*
用于预检请求的响应。其指明了实际请求中允许携带的首部字段。

Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
Cookie曾一度用于客户端数据的存储,随着现代浏览器开始支持各种各样的存储方式,Cookie渐渐被淘汰。
新的浏览器API已经允许开发者直接将数据存储到本地,如使用storage(本地存储和会话存储)或IndexedDB 。

HTTP/2在HTTP/1.1有几处基本的不同:
    HTTP/2是二进制协议而不是文本协议。不再可读,也不可无障碍的手动创建,改善的优化技术现在可被实施。
    这是一个复用协议。并行的请求能在同一个链接中处理,移除了HTTP/1.x中顺序和阻塞的约束。
    压缩了headers。因为headers在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本。
    其允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求。

HTTPS协议是由HTTP加上TLS/SSL协议构建的可进行加密传输、身份认证的网络协议实现互联网传输安全保护。
服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。

设计目标主要有三个:
	(1)数据保密性:保证数据内容在传输的过程中不会被第三方查看。
	(2)数据完整性:及时发现被第三方篡改的传输内容。
	(3)身份校验安全性:保证数据到达用户期望的目的地。

* 在TLS1.3中,废除了RSA和DH算法,使用了更加安全的ECDHE。

一次完整的https请求过程:
1. DNS查询
	根据优先级从浏览器DNS缓存、操作系统的DNS缓存、hosts文件、电信运营商的本地DNS缓存、运营商的根DNS服务器获取IP。
2. 三次握手建立TCP连接
3. 密钥协商(以ECDHE四次握手为例)
	(1) c->s(client-hello): 支持的密码套件列表、TLS版本号、随机数client-random
	(2) s->c(server-hello): 选择的密码套件、确认TLS版本号、随机数server-random
	    s->c(certificate): 发送数字证书
	    s: 生成一对椭圆曲线公私钥spub和spri
	    s->c(server-key-exchange): 发送用RSA加密的spub
	    s->c(server-hello-done): 招呼完毕
	(3) c: 校验证书
	    c: 生成一对椭圆曲线公私钥cpub和cpri
	    c->s(client-key-exchange): 发送用RSA加密的cpub
	    c->s(change-cipher-spec): 告诉服务端后续改用对称加密通信
	    c: cpri+spub算出预主密钥pre-master,client-random+server-random+pre-master生成主密钥
	    c->s(encrypted-handshake-message): 发送密钥加密后的握手数据摘要
	(4) s->c: (change-cipher-spec): 告诉服务端后续改用对称加密通信
	    s: spri+cpub算出预主密钥pre-master,client-random+server-random+pre-master生成主密钥
	    s->c: (encrypted-handshake-message): 发送密钥加密后的握手数据摘要
4. 使用密钥进行加密数据传输
	如果使用了RSA密钥协商算法,TLS完成四次握手后,才能进行应用数据传输;
	而对于ECDHE算法,客户端可以不用等服务端的最后一次TLS握手,就可以提前发出加密的数据。
5. 四次握手断开TCP连接