HTTP(HyperText Transfer Protocol,超文本传输协议)通信通常通过TCP/IP连接进行,默认端口是TCP 80,但可以使用其他端口,以ASCII码传输。这并不妨碍HTTP在任何其他协议之上实现,HTTP只是假定了一个可靠的传输,任何能够提供可靠传输的协议都能够被使用。
灵活可扩展
Content-Type
设置类型)。可靠传输
(默认)基于TCP/IP。
client-server协议
使用HTTP时,必定是一端担任客户端角色,另一端担任服务器端角色。虽然客户端和服务器端的角色可能会互换,但一条通信路线中角色是确定的。请求由客户端开始。
C/S、B/S结构。
无状态(cookie弥补)
通信过程不保存上下文信息,每次HTTP请求都是独立、无关的。
无连接、短连接(持久连接弥补)
每次TCP连接只处理一个请求-响应。每一次完整的HTTP通信都要建立单独的TCP连接,服务器处理完客户的请求、并收到客户的应答后,即断开TCP连接。可以节省传输时间。
TCP/IP协议族:利用IP进行通信时所必须用到的协议群的统称,是为使用互联网而开发制定的协议族。
分层
OSI模型 和 TCP/IP协议四层模型
OSI是一种理论下的模型,未被直接应用;TCP/IP已被广泛使用,成为网络互联事实上的标准。
应用层:HTTP、WebSocket、DNS、FTP(File Transfer Protocol,文件传输协议)
决定了向用户提供应用服务时通信的活动。
SSL位于应用层和传输层中间。
传输层:TCP、UDP
对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。
网络层:IP
处理在网络上流动的数据包(网络传输的最小数据单位)。该层规定了通过怎样的传输路径到达对方计算机,并把数据包传送给对方。与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选择中选择一条传输路径。
数据链路层:
处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网络适配器,网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围内。
发送端从应用层往下传递,接收端则往应用层上传递:
与HTTP相关的协议
应用层:DNS(Domain Name System,域名系统)
提供域名到IP地址之间的解析服务:通过域名查找IP地址、逆向通过IP地址反查域名。
计算机可以被赋予IP地址、主机名、域名。同一个服务器上的多个域名,使用DNS服务解析域名为同一个IP地址,因此在发送HTTP请求时,必须设置
Host
头部为指定主机名或域名的URI。
传输层:TCP(Transmission Control Protocol,传输控制协议)
提供可靠的字节流服务(Byte Stream Service):
网络层:IP(Internet Protocol,网际协议)
把各种数据包经过中转传送给对方。使用ARP协议(Address Resolution Protocol)凭借MAC地址(Media Access Control Address)进行通信:
IPv4与IPv6的路由和寻址数量:
IPv4
Math.pow(2, 32) === Math.pow(256, 4)
,如:183.2.223.26
。
IPv6
Math.pow(2, 128) === Math.pow(16, 32)
,如:2001:0db8:86a3:08d3:1319:8a2e:0370:7344
。
在某些情况下,一个IPv6地址中间可能包含很长的一段
0
,可以把连续的一段0
压缩为::
。但为保证地址解析的唯一性,地址中::
只能出现一次。e.g.
FF01:0:0:0:0:0:0:1101 → FF01::1101 0:0:0:0:0:0:0:1 → ::1 0:0:0:0:0:0:0:0 → ::
HTTP协议版本区别
TCP协议头部的部分字段
1. `sequence number`(`seq`) 资源的数据序列。 2. `acknowledgement number`(`ack`) 对方所期望接收到的下一个序号,是上次已成功接收到`seq+1`。 3. `ACK` `1`:应答域(acknowledgement number)有效;`0`:应答域无效。 4. `SYN` 用来建立连接。`SYN=1,ACK=0`:请求连接;`SYN=1,ACK=1`:响应连接。 5. `FIN` 自己数据已经传输完成,断开自己的连接。
建立连接的三次握手
SYN=1,seq=客户端序号
的连接请求。SYN=1,seq=服务端序号,ACK=1,ack=客户端序号+1
的响应消息。ACK=1,ack=服务端序号+1
的确认消息。断开连接的四次挥手
FIN=1,seq=主机A序号
的断开信息。ACK=1,ack=主机A序号+1
的响应消息。FIN=1,seq=主机B序号
的断开信息。ACK=1,ack=主机B序号+1
的响应消息。设计原因
1. 三次握手原因:为了防止已失效的连接请求报文段突然又传送到服务端,让服务端误判后单方面建立连接。 1. client早先发出的连接请求报文段并没有丢失,而是在某个网络结点长时间滞留,以致延误到client连接释放以后的某个时间才到达server; 2. 本来这是一个早已失效的报文段,但server收到此失效的连接请求报文段后,误认为是client发出的一个新的连接请求,于是就向client发出确认报文段,同意建立连接。 1. 假设不采用「三次握手」,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。 2. 采用「三次握手」的办法可以防止上述现象发生,client不会向server的确认发出确认,server由于收不到确认,就知道client并没有要求建立连接。 2. 四次挥手原因:TCP是**全双工模式**(通信允许数据在两个方向上同时传输),需要通信的双方都确认才断开。 1. 当主机A发出FIN报文段时,只表示主机A已经没有数据要发送了;但是,这个时候主机A还是可以接受来自主机B的数据; 2. 当主机B返回ACK报文段时,表示主机B已经知道主机A没有数据发送了,但是主机B还是可以发送数据到主机A; 3. 当主机B也发送了FIN报文段时,这个时候就表示主机B也没有数据要发送了; 4. 当收到主机A返回ACK报文段时,表示主机A已经知道主机B没有数据发送了,之后彼此都中断这次TCP连接。
获取域名的IP地址
DNS解析:浏览器自身DNS缓存 -> 操作系统DNS缓存 -> 本地hosts文件 -> 路由器DNS缓存 -> 宽带运营商。
建立TCP/IP连接
发起「三次握手」(验证客户端),试图建立TCP/IP链接。
关闭TCP链接要「四次挥手」。
浏览器发送HTTP请求,服务器响应
服务器端接受请求,根据路径参数、经过后端处理之后,把结果的数据返回浏览器。
request:
<method> <request-URI> <version> // 请求行
<headers> // 请求头
// 空行(CR+LF)
<entity-body> // 请求消息主体
response:
<version> <status code> <reason phrase> // 状态行
<headers> // 响应头
// 空行(CR+LF)
<entity-body> // 响应正文
e.g.
1. request ```http POST /home/ HTTP/1.1 Accept: */* User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727) Host: a.com Content-Length: 465 Pragma: no-cache {"info":""} ``` 2. response ```http HTTP/1.1 200 OK Server: nginx/1.9.15 Date: Tue, 27 Feb 2018 08:40:25 GMT Content-Type: application/json;charset=UTF-8 Content-Length: 979 Cache-Control: max-age=0 Proxy-Connection: Close {"errno":0,"errmsg":"","data":{""}} ```
来自:MDN:HTTP 请求方法。
GET:通常用来获取资源
向指定的资源发出「显示」请求。使用GET方法应该只用在读取数据,而不应当被用于产生「副作用」的操作中。
POST:提交数据
向指定资源提交数据,请求服务器进行处理(如:提交表单或上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
PUT:修改数据
向指定资源位置上传最新内容(文件)。
DELETE:删除资源(几乎用不到)
请求删除指定资源位置的内容。
HEAD:获取资源的元信息
与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。在不必传输全部内容的情况下,获取关于该资源的信息(HTTP响应头)。
OPTIONS:列出可对资源实行的请求方法,用来跨域请求
使服务器传回该资源所支持的所有HTTP请求方法。用「*」来代替资源名称,测试服务器功能是否正常运作。
TRACE:追踪请求-响应的传输路径
回显服务器收到的请求,主要用于测试或诊断。
CONNECT:建立连接隧道,用于代理服务器
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。
PATCH:修改局部数据
用于将局部修改应用到资源。
LINK
(已废弃)
UNLINK
(已废弃)
语义区别
副作用
当发送完一个请求后,网站上的资源状态发生修改,即认为这个请求有副作用;反之,则无副作用。
幂等性(idempotence)
多次请求某一个资源应该具有同样的副作用。
请求类型 | 幂等 | 副作用 | 请求消息主体 |
---|---|---|---|
GET | 幂等 | 无副作用 | 一般不携带 |
POST | 非幂等 | 副作用 | 携带 |
PUT | 幂等 | 副作用 | 携带 |
DELETE | 幂等 | 副作用 | 一般不携带 |
用以表示服务器HTTP响应状态的3位数字代码。
1XX中间状态信息
代表请求已被接受,需要继续处理;代表临时性、信息性的响应,只包含状态行和某些可选的响应头信息,始终以消息头后的第一个空行结尾;标示客户端应该采取的其他行动。
100 Continue
客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或若请求已经完成,则忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应。
101 Switching Protocols
服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。在发送完这个响应最后的空行后,服务器将会切换到在Upgrade消息头中定义的那些协议。如:HTTP升级为WebSocket。
102 Processing
处理将被继续执行。
2XX成功
代表请求已成功被服务器接收、理解,并接受。
200 OK
请求已成功,请求所希望的响应头或数据体将随此响应返回。
201 Created
请求已经被实现,而且有一个新的资源已经依据请求的需要而创建,且其URI已经随Location头信息返回。
202 Accepted
服务器已接受请求,但尚未处理。正如它可能被拒绝一样,最终该请求可能会也可能不会被执行。在异步操作的场合下,没有比发送这个状态码更方便的做法了。
203 Non-Authoritative Information
服务器已成功处理了请求,但返回的实体头部元信息不是在原始服务器上有效的确定集合,而是来自本地或第三方的复制。当前的信息可能是原始版本的子集或超集。
204 No Content
服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息(与200 OK相同,但没有响应实体)。始终以消息头后的第一个空行结尾。
205 Reset Content
服务器成功处理了请求,且没有返回任何内容,并且要求请求者重置文档视图。该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。始终以消息头后的第一个空行结尾。
206 Partial Content
服务器已经成功处理了部分GET请求。分块下载、断点续传,会带上响应头Content-Range
。
207 Multi-Status
代表之后的消息体将是一个XML消息,并且可能依照之前子请求数量的不同,包含一系列独立的响应代码。
3XX重定向
代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。
300 Multiple Choices
被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。用户或浏览器能够自行选择一个首选的地址进行重定向。
301 Moved Permanently
被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。浏览器默认会做缓存优化,在第二次访问的时候自动访问重定向的那个地址。
302 Moved Temporarily或302 Found
被请求的资源临时从不同的URI响应请求。
303 See Other
被请求的资源临时从不同的URI响应请求,且客户端应当把POST转化为GET方式访问那个资源。
304 Not Modified
协商缓存命中时会返回。始终以消息头后的第一个空行结尾。
305 Use Proxy
被请求的资源必须通过指定的代理才能被访问。
306 Switch Proxy
(已废弃)
307 Temporary Redirect
被请求的资源临时从不同的URI响应请求,且客户端不会把POST转化为GET访问那个资源。
4XX客户端错误
代表客户端看起来可能发生了错误,妨碍了服务器的处理。
400 Bad Request
当前请求无法被服务器理解。
401 Unauthorized
当前请求需要用户验证。
402 Payment Required
(预留)
403 Forbidden
服务器已经理解请求,但是拒绝执行它。
404 Not Found
资源未找到。
405 Method Not Allowed
请求行中指定的请求方法不能被用于请求相应的资源。
406 Not Acceptable
请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。返回Allow
响应头。
407 Proxy Authentication Required
与401响应类似,只不过客户端必须在代理服务器上进行身份验证。
408 Request Timeout
请求超时。
409 Conflict
由于和被请求的资源的当前状态之间存在冲突,请求无法完成。
410 Gone
被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。
411 Length Required
服务器拒绝在没有定义Content-Length头的情况下接受请求。
412 Precondition Failed
服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。
413 Request Entity Too Large
服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或能够处理的范围。
414 Request-URI Too Long
请求的URI长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务。
415 Unsupported Media Type
对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝。
416 Requested Range Not Satisfiable
若请求中包含了Range请求头,并且Range中指定的任何数据范围都与当前资源的可用范围不重合,同时请求中又没有定义If-Range请求头。
417 Expectation Failed
在请求头Expect中指定的预期内容无法被服务器满足,或这个服务器是一个代理服务器,它有明显的证据证明在当前路由的下一个节点上,Expect的内容无法被满足。
418 I’m a teapot
客户端错误响应代码表示服务器拒绝冲泡咖啡,因为它是一个茶壶(这个错误是超文本咖啡壶控制协议的参考,这是1998年愚人节的笑话)。
421 There are too many connections from your internet address
从当前客户端所在的IP地址到服务器的连接数超过了服务器许可的最大范围。
422 Unprocessable Entity
请求格式正确,但是由于含有语义错误,无法响应。
423 Locked
当前资源被锁定。
424 Failed Dependency
由于之前的某个请求发生的错误,导致当前请求失败,如:PROPPATCH。
425 Unordered Collection
(未出现)
426 Upgrade Required
客户端应当切换到TLS/1.0。
429 Too Many Requests
客户端发送的请求过多。
431 Request Header Fields Too Large
请求头的字段内容太大。
449 Retry With
由微软扩展,代表请求应当在执行完适当的操作后进行重试。
451 Unavailable For Legal Reasons
(已废弃)
5XX服务器错误
代表服务器在处理请求的过程中有错误或异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。
500 Internal Server Error
服务器出错。
501 Not Implemented
服务器不支持当前请求所需要的某个功能。
502 Bad Gateway
作为网关或代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503 Service Unavailable
由于临时的服务器维护或过载,服务器当前无法处理请求。
504 Gateway Timeout
作为网关或代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,如:HTTP、FTP、LDAP)或辅助服务器(如:DNS)收到响应。
505 HTTP Version Not Supported
服务器不支持,或拒绝支持在请求中使用的HTTP版本。
506 Variant Also Negotiates
代表服务器存在内部配置错误:被请求的协商变元资源被配置为在透明内容协商中使用自己,因此在一个协商处理中不是一个合适的重点。
507 Insufficient Storage
服务器无法存储完成请求所必须的内容。
509 Bandwidth Limit Exceeded
服务器达到带宽限制。
510 Not Extended
获取资源所需要的策略并没有被满足。
作用:
添加附加信息、操作参数,用来准确描述正在获取的资源、发送端的行为。
结构:
不区分大小写的属性名后跟一个冒号,再紧跟它的值(不换行)组成,以回车(CR)换行(LF)
符号序列结尾。值的内容可以以;
分割(,
分割单词)。值前面的空格会被忽略掉。自定义专用消息头可通过X-
前缀来添加(已废弃。现在不再根据是否有X-
前缀来鉴别是否是自定义头)。
类型
具体内容:MDN:HTTP 消息头、rfc4229。
通用头部字段(general)
同时适用于请求和响应,但与最终消息主体中传输的数据无关的消息头。
通用头部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Pragma | 仅有Pragma: no-cache 一个值,与Cache-Control: no-cache 效果一致,强制要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行验证 |
Connection | 逐跳头部(控制不再转发给代理的头部)、持久连接的管理 |
Date | 创建报文的日期时间 |
Trailer | 报文末端的头部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息。若这个请求经过了多个代理层,则Via头部就会有多个网关信息 |
Warning | 附加的警告信息 |
实体头部字段(entity)
同时适用于请求和响应,包含有关实体主体的更多信息。
实体头部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP请求方法 |
Content-Encoding | 实体主体适用的编码方式(如:gzip) |
Content-Language | 实体主体的语言(自然语言) |
Content-Length | 实体主体的大小(字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围,表示传输的Body数据在整体资源块中的字节范围 |
Content-Type | 实体主体的媒体类型(Multipurpose Internet Mail Extensions,MIME types)和编码格式。无论是前端还是后端发起,Content-Type 必须要与传输的数据类型一一对应,否则解析失败 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
请求头部字段(request)
包含更多有关要获取的资源或客户端本身信息的消息头。
请求头部字段名 | 说明 |
---|---|
Origin | 请求源 |
Accept | 用户代理可处理的媒体类型,表示客户端期望服务器返回的媒体格式 |
Accept-Charset | 优先的字符集,表示客户端期望服务器返回的内容的编码格式 |
Accept-Encoding | 优先的内容编码,表示客户端期望服务器返回的编码 |
Accept-Language | 优先的语言(自然语言),表示客户端期望服务器返回的语言 |
TE | 优先的传输编码 |
Authorization | 服务器要求客户端的认证信息(令牌),对响应头WWW-Authenticate的应答 |
Proxy-Authorization | 代理服务器要求客户端的认证信息(令牌) |
Expect | 用于请求发送之前向服务器询问许可 |
From | 用户的电子邮箱地址 |
Host | 请求资源的主机名(必须添加)。一般无法修改,由请求URL确定 |
If-Match | 比较实体标记(ETag),相同则服务器接受请求 |
If-None-Match | 比较实体标记(ETag),不同则服务器接受请求 |
If-Modified-Since | 比较资源的更新时间(Last-Modified),之后时间有更新则服务器接受请求 |
If-Unmodified-Since | 比较资源的更新时间(Last-Modified),之后时间没有更新则服务器接受请求 |
If-Range | 比较ETag或Last-Modified,相同则作为范围请求处理;反之,则返回全体资源 |
Range | 实体的字节范围请求。断点续传,它表示客户端请求资源的一部分时指定的请求字节范围 |
Max-Forwards | 最大传输逐跳数 |
Referer | 发起请求的页面的上一个页面的URL |
User-Agent | HTTP客户端程序的信息 |
Cookie | 客户端存在的cookie(一次发送所有相关cookie) |
形如
If-xxx
这种样式的请求头部字段,都可称为条件请求。服务器接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。
响应头部字段(response)
包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头。
响应头部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间(秒) |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI。302跳转时,Location为目标URL |
WWW-Authenticate | 服务器对客户端的认证信息。401 Unauthorized错误码返回时必须携带 |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 服务器升级时,客户端的请求会直接给予503(Service Unavailable)错误,通过在响应头里面加入Retry-After字段告知客户端何时服务可以恢复正常访问 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
Set-Cookie | 服务端设置客户端cookie(一次可发送多个cookie) |
Content-Security-Policy | 控制用户代理在一个页面上可以加载使用的资源 |
缓存、代理是否转发
逐跳(hop-by-hop)
只对单次转发有效,会因通过缓存或代理而不再转发。需提供Connection
头部字段。
Connection
、Keep-Alive
、Proxy-Authenticate
、Proxy-Authorization
、Trailer
、TE
、Transfer-Encoding
、Upgrade
端到端(end-to-end)
会转发给请求、响应对应的最终接收目标,且必须保存在由缓存生成的响应中。
除了上面8个。
参考:浏览器缓存知识小结及应用。
只缓存GET请求。
强缓存(本地缓存,Freshness)
浏览器加载资源时,先根据这个资源之前响应头的Expires
、Cache-Control
判断它是否命中强缓存(判断是否到了过期时间)。
命中状态码:
200 OK (from 某某 cache)
Chrome的DevTools的Network会显示该资源的Request Headers:
Provisional headers are shown.
利用之前HTTP response header返回的Expires
和Cache-Control
Cache-Control
的优先级高于Expires
(当服务器同时使用时,忽略Expires)。
Expires
:
绝对时间。HTTP/1.0提出。
浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,会返回一系列响应头;
Expires响应头表示资源过期的绝对时间。
浏览器再请求这个资源时,先从缓存中寻找。找到这个资源后,拿出它的Expires跟当前的请求时间进行对比:
200 OK (from 某某 cache)
,从本地缓存中读取资源,不会发请求到服务器。Cache-Control
:
相对时间。秒级。HTTP/1.1提出。
浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,会返回一系列响应头;
Cache-Control响应头表示(相对于请求发起时间的)资源过期的相对时间。
浏览器再请求这个资源时,先从缓存中寻找。找到这个资源后,根据它请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间进行对比:
若请求头设置
cache-control: max-age=0
,则忽略强缓存(本地缓存),直接进行协商缓存。
200 OK (from 某某 cache)
,从本地缓存中读取资源,不会发请求到服务器。启发式缓存(Heuristic Freshness)
只有在服务端没有返回明确的缓存策略时才会激活浏览器的启发式缓存策略。
若一个资源响应头未设置 、Expires
,但响应头有设置Cache-Control
Last-Modified
信息,则浏览器会有一个默认的缓存策略(效果、状态码等,与 强缓存 一致),缓存时间:(响应头的Date - 响应头的Last-Modified) * 0.1
。
协商缓存(Validation)
若没有命中强缓存,浏览器发送一个请求到服务器,服务端根据这个资源的If-Modified-Since
(Last-Modified
)、If-None-Match
(ETag
)判断它是否命中协商缓存(判断缓存资源和服务端资源是否一致)。
命中状态码:
304 Not Modified
利用之前HTTP response header返回的Last-Modified
、ETag
作为HTTP request head发起的If-Modified-Since
、If-None-Match
ETag/If-None-Match
的优先级高于Last-Modified/If-Modified-Since
(当服务器同时使用时,先判断If-None-Match。若中协议缓存,再判断If-Modified-Since;若没有中,不再判断)。
Last-Modified
与If-Modified-Since
:
绝对时间。服务器时间。秒级。
浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,会返回一系列响应头;
Last-Modified响应头表示这个资源在服务器上的最后修改时间。
服务器收到资源请求时,拿If-Modified-Since和资源在服务器上最后修改时间进行对比:
304 Not Modified
,但不返回资源内容。浏览器从本地缓存中读取资源。分布式部署,多台机器的Last-Modified必须保持一致。
ETag
与If-None-Match
:
浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,会返回一系列响应头;
ETag响应头表示这个资源在服务器上的唯一标识字符串,只要资源有变化这个串就改变。
服务器收到资源请求时,拿If-None-Match和资源在服务器上生成新的ETag进行对比:
Last-Modified/If-Modified-Since
),返回304 Not Modified
,但不返回资源内容。浏览器从本地缓存中读取资源。使用选择
ETag
的缺陷
ETag
的必要性
因此具体某个资源只需运用ETag或Last-Modified的两者之一。
强缓存与协商缓存的联系:
相同:
区别:
用户行为影响缓存使用情况
用户操作 | 强缓存 | 协商缓存 |
---|---|---|
地址栏回车 | 有效 | 有效 |
页面链接跳转 | 有效 | 有效 |
新开窗口 | 有效 | 有效 |
前进、后退 | 有效 | 有效 |
刷新 | 无效 | 有效 |
强制刷新 | 无效 | 无效 |
AJAX
异步加载,局部更新。
Comet
延迟响应。
WebSocket
HTTP不足
无法证明报文的完整性,可能已遭篡改。
中间人攻击(Man-In-The-Middle attack,MITM)。
HTTPS(HTTP Secure) = HTTP + 通信加密 + 证书认证 + 完整性保护
HTTPS并非是应用层的一种新协议。只是HTTP通信接口部分用SSL(Secure Socket Layer)或TLS(Transport Layer Security)协议代替(在应用层和传输层中间添加)。
加密
对称密钥加密(Common key crypto system,共享密钥加密)
加密和解密同用一个密钥,必须将密钥发送给对方。
非对称加密(Public-key cryptography,公开密钥加密):
处理速度较慢、安全性很高。
发送密文的一方使用对方的公开密钥进行加密,对方收到被加密信息后再使用自己的私有密钥进行解密。
设计逻辑
它需要两个密钥,一个是公开密钥,另一个是私有密钥;一个用作加密,另一个则用作解密。使用其中一个密钥把明文加密后所得的密文,只能用相对应的另一个密钥才能解密得到原本的明文;甚至连最初用来加密的密钥也不能用作解密。虽然两个密钥在数学上相关,但若知道了其中一个,则并不能凭此计算出另外一个;因此其中一个可以公开,称为公钥,任意向外发布;不公开的密钥为私钥,必须由用户自行严格秘密保管,绝不通过任何途径向任何人提供,也不会透露给要通信的另一方,即使他被信任。
加密保证 = 对称密钥加密 + 非对称加密
认证:公开密钥的证书。
由发布机构CA保证。
完整:附加MAC(Message Authentication Code)报文摘要判断是否遭到篡改。
为什么不一直使用HTTPS
Mixed Content
。一套互联网安全策略机制,强制浏览器使用HTTPS与网站进行通信(避免:先发出HTTP请求再302重定向为HTTPS),以减少会话劫持风险。
必要性:HTTPS也不够安全
浏览器向网站发起一次HTTP请求,在得到一个要求重定向的响应后,发起一次302重定向的HTTPS请求并得到最终的响应内容。在HTTP请求时,容易受到中间人攻击。
开启HSTS方法:当客户端通过HTTPS发出请求时,在服务器返回的HTTP响应头中包含Strict-Transport-Security
。
Strict-Transport-Security: max-age=秒数[; includeSubDomains][; preload]
效果(在有效期内、或域名在HSTS preload list内)
HSTS preload list(浏览器预置HSTS域名列表),包含的域名硬编码进浏览器从而对这些域名默认开启HSTS保护。
可以在Chrome地址栏输入
chrome://net-internals/#hsts
查看HSTS包含的域名情况。
Mixed Content
Mixed Content
(混合内容):初始HTML内容通过安全的HTTPS连接加载(.html),但其他资源(如:样式表、脚本、图像、多媒体资源等)通过不安全的HTTP连接加载。
现代浏览器会显示警告/错误,以向用户表明此页面包含不安全的资源
被动混合内容(提示warning,但还可以正常发出请求):
<img>
的src
<audio>
的src
video
的src
object
的子资源主动混合内容(提示error,阻止发出请求):
<script>
的src
<link>
的href
@font-sace
、cursor
、background-image
、等)<picture>
的子资源(如:<img>
)XMLHttpRequest
请求<iframe>
的src
<object>
的data
navigator.sendBeacon
请求让页面中发起的HTTP请求自动转化为HTTPS请求进行发出:
HTTP响应头:
Content-Security-Policy: upgrade-insecure-requests;
.html
的<meta>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
HTTP持久连接(HTTP长连接,HTTP Persistent Connections,HTTP keep-alive,HTTP connection reuse)
只要任意一端没有明确提出断开连接,则保持TCP连接状态,(不用重复连接)可以完成多个HTTP请求。单个客户端与服务器和代理服务器之间不应该维持超过2个持久连接。
Connection: Keep-Alive
。持久连接的管线化(pipelining):将多个HTTP请求整批提交,但服务端必须按照顺序整批返回。(非管线化:发送请求后,需要收到响应了才能发送下一个请求)
WebSocket
新的全双工通讯协议。在TCP建立之后,复用HTTP的握手通道,再进行一次握手后创建连接。
String
)、二进制数据(Blob
实例或Arraybuffer
实例)。协议标识符ws
,默认端口80
;加密协议标识wss
,默认端口443
。
e.g.
ws://example.com:80/some/path
、wss://example.com:443/some/path
相关头
请求头:
Connection: Upgrade
、Upgrade: websocket
、Sec-WebSocket-Key
响应头:
Connection: Upgrade
、Upgrade: websocket
、Sec-WebSocket-Accept
HTTP/2
主要基于SPDY协议演变而来
主要区别: 1. HTTP/2支持明文HTTP传输;SPDY强制使用HTTPS。 2. HTTP/2消息头的压缩算法采用HPACK;SPDY采用DEFLATE。
与HTTP/1.1完全语义兼容,进一步减少网络延迟:
2进制分帧
在应用层(HTTP/2)和传输层(TCP/UDP)间增加一个2进制分帧层。
多路复用(multiplexing)
流(stream)、帧(frame)。
允许通过单一连接(TCP)建立双向字节流。
HTTP/3是即将到来的第三个主要版本的HTTP协议。与其前任HTTP/1.1和HTTP/2不同,在HTTP/3中,将弃用TCP协议,改为使用基于UDP协议的QUIC协议(快速UDP网络连接)实现。
参考:跨域资源共享 CORS 详解。
若服务端配置允许了某些或所有域名,就可以跨域响应;前端不需要进行额外工作,现代浏览器自动完成交互:
ie10+支持。
现代浏览器一旦发现XMLHttpRequest
或fetch
等请求跨源,会自动添加一些附加的头信息(如:Origin
),有时还会多出一次附加的请求(非简单请求的OPTIONS
请求)。
简单/非简单请求区分
- 同时满足以下两个条件为简单请求,否则为非简单请求: 1. 请求方法: `HEAD`或`GET`或`POST`。 2. 请求头仅包含(浏览器自动添加的其他请求头也可以是简单请求): 1. `Accept` 2. `Accept-Language` 3. `Content-Language` 4. `Content-Type`仅限于`application/x-www-form-urlencoded`或`multipart/form-data`或`text/plain`
简单请求(simple request)
HTTP请求:
请求头需要:Origin
(来自的域)。
响应:
允许跨域,则响应头包含:
Access-Control-Allow-Origin
:值为请求头Origin
的值或*
,表明接受跨域请求
若
Access-Control-Allow-Credentials
为true
,则Access-Control-Allow-Origin
不能为*
,需要是明确的、与请求网页一致的域名。
Access-Control-Allow-Credentials
:(可选)是否允许发送Cookie
XMLHttpRequest
要设置withCredentials
为true
,浏览器才会发送。
Access-Control-Expose-Headers
:(可选)CORS请求时,XMLHttpRequest
只能拿到6个基本字段(Cache-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
),若需要其他字段,需在此指定
不允许跨域:
若Origin
指定的源不在许可范围内,服务器会返回一个正常的HTTP响应(状态码200,并可以返回正确数据),但没有任何CORS相关的头信息字段。浏览器根据响应头没有包含Access-Control-Allow-Origin则认定为跨域错误(被XMLHttpRequest
的onerror
回调函数捕获)。
非简单请求(not-so-simple request)
非简单请求是那种对服务器有特殊要求的请求。先发起的预检请求可以避免跨域请求对服务器数据产生未预期的副作用;得到服务端允许后,浏览器才会发送正式的跨域请求(与简单请求一致)。
预检请求
浏览器判断为非简单请求,自动发出OPTIONS
方法的HTTP请求:
请求头需要:Origin
(来自的域)、Access-Control-Request-Method
(需要进行跨域的请求方法)、Access-Control-Request-Headers
(需要额外发送的头信息字段)。
响应:
允许跨域,则响应头包含:
Access-Control-Allow-Origin
:值为请求头Origin
的值或*
,表明接受跨域请求
若
Access-Control-Allow-Credentials
为true
,则Access-Control-Allow-Origin
不能为*
,需要是明确的、与请求网页一致的域名。
Access-Control-Allow-Methods
:服务器支持的所有跨域请求的请求方法Access-Control-Allow-Headers
:(若HTTP请求头有Access-Control-Request-Headers
则必须)服务器支持的所有跨域请求的请求头字段,以,
分割Access-Control-Allow-Credentials
:(可选)是否允许发送Cookie
XMLHttpRequest
要设置withCredentials
为true
,浏览器才会发送。
Access-Control-Max-Age
:(可选)本次预检请求的有效期,单位秒不允许跨域:
若服务器否定了预检请求,服务器会返回一个正常的HTTP响应,但没有任何CORS相关的头信息字段。浏览器根据响应没有包含相关响应头则认定为跨域错误(被XMLHttpRequest
的onerror
回调函数捕获)。
一旦服务器通过预检请求,之后的每次跨域请求都与简单请求一致。
HTTP是无状态协议,通过session-cookie或token判断客户端的用户状态。
session-cookie
同源认证(因为利用cookie)解决方案。
session(会话)
服务器为了保存客户端状态,给每个客户端分配不同的「身份标识」(保存在服务器,过期后销毁),客户端发请求时需要携带该标识。
session的运作通过session_id进行,session_id通常会保存在客户端的cookie中。
cookie
服务器生成,发送给客户端保存(Set-Cookie
),再由客户端发送给服务器(Cookie
)。cookie携带session_id(可以经过加密),能够匹配服务端的session。
token(令牌)
最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(加盐后哈希)。
认证用户,授权App。针对App与服务端的无状态API。与session-cookie方式没有直接关系、可一起使用、不冲突。
行业标准授权协议。
主要用来授权第三方应用获取有限的网页权限。登录平台经过用户授权,为第三方应用颁发一个有时效性的token,第三方应用能够通过该token获取登录平台的部分资源。
跨域认证解决方案。
服务器认证以后,生成一个JSON对象(转成特殊结构的字符串),发回给客户端,客户端本地保存,当客户端与服务端通信时,都要发回这个token。服务端不保存任何session数据、变成无状态,从而比较容易实现扩展。
e.g. 服务A在认证了用户身份后,颁发一个很短过期时间的JWT给客户端,若客户端在向服务B的请求中带上该JWT,则服务B可以通过验证该JWT来判断用户是否有权执行服务B上的相关操作。
从已经登录的客户端提取出登录信息(session_id或token),传递给其他客户端,再由其他客户端把登录信息注入cookie,就可以转移登录状态到其他客户端。
URI = URL + URN
URI(Uniform Resource Identifier,统一资源标志符)
标识一个资源。
URL(Uniform Resource Locator,统一资源定位符)
提供找到一个资源的地址。
URN(Uniform Resource Name,统一资源名称)
(已不推荐使用)
URI的结构:scheme
://
user:passwd@
host:port
path
?query
#fragment
URL的锚点(
#fragment
)不会出现在HTTP请求中,因此可以避免中间人攻击。
协议(protocol):
计算机与网络设备要互相通信,双方就必须基于相同的方法,确定的规则就是协议。
如何探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定。
通信数据转发程序
代理
有转发功能的应用程序,扮演着位于服务器和客户端「中间人」的角色,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。
包括:缓存代理(先将资源保存在代理)、透明代理(不加工报文)、非透明代理。
每次通过代理服务器转发请求或响应时,会追加写入
Via
头信息。
正向、反向代理:
网关(gateway)
隧道
在相隔甚远的客户端和服务器两者之间进行中转,使双方保持安全连接的应用程序。
CDN(Content Delivery Network,内容分发网络)
在不同的地点创建缓存代理服务器,通过负载均衡技术、最优节点选择,将用户的请求重定向到最合适的缓存代理服务器(缓存整个HTTP请求-响应),减少源站的压力、提升加载速度。
回源:当有用户访问某一个URL时,若被解析到的那个CDN节点没有缓存响应的内容、或缓存已经到期,则会回源站去获取。
CDN的地址后增加
?xx
,大部分情况当做一个新的资源,可用于强制回源(注意不要在代码中使用增加时间戳的CDN,否则每次都回源)。若使用HTTPS的CDN,回源也必须用HTTPS,全链路HTTPS堵死运营商劫持。
UDP(User Data Protocol,用户数据报协议)
ping
命令来测试两台主机之间TCP/IP通信是否正常,原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,若数据包是否到达的消息及时反馈回来,则网络就是通的。
TCP与UDP的区别:
区别 | TCP | UDP |
---|---|---|
连接性 | 面向连接,建立连接后(三次握手)才传输数据。 | 面向非连接,发送数据前不需建立连接。 |
可靠性 | 提供可靠的服务(数据无差错、不丢失、不重复、按序到达)。 | 尽最大努力交付,不保证可靠性(任何必需的可靠性须由应用层提供)。 |
拥塞控制 | 面向字节流(把数据看成一连串无结构的字节流),有流量控制(拥塞控制)。 | 面向报文,没有拥塞控制(网络出现拥塞不会使源主机的发送速率降低)。 |
交互方式 | 点到点。 | 一对一、一对多、多对一、多对多。 |
有序性 | 消息在传输过程中可能会乱序,后发送的消息可能会先到达,TCP会对其进行重新排序。 | 无序。 |
协议头部字节数 | 20字节。 | 8字节。 |
传输速度 | 慢(需要建立连接、保证可靠性、有序性) | 快 |
最短的单次client-server发送数据包次数 | 三次握手初始化TCP + 查询包 + 响应包 + 四次分手断开TCP = 9 | 查询包 + 响应包 = 2 |
在注重性能、传输速度且不需要重传的应用(如:视频电话、即时通讯),会选择使用UDP。其他情况,when in doubt, use TCP。
127.x.x.x
本地环回地址,主要用于测试或网络管理/路由更新,比物理接口稳定。
127.0.0.1
只要使用这个地址发送数据,则数据包不会出现在网络传输过程中。
10.x.x.x
、172.16.x.x~172.31.x.x
、192.168.x.x
私网地址,不与外网相连。
255.255.255.255
广播地址(向网关获取本机IP地址)。
0.0.0.0
源IP地址,发生在当设备启动时但又不知道自己IP地址的情况下。路由表中无法查询的包都将送至全零网络的路由。