from 从输入 URL 到页面加载的过程?如何由一道题完善自己的前端知识体系!
作为进阶回头再来看看:从输入 URL 到页面加载完成的过程中都发生了什么事情?
后台和前台的 http
交互
http
信息载体
报文一般包含了 通用头部 响应/请求头部 响应/请求体
通用头部
Request URL
请求的web
服务器地址Request Method
请求的方法(get
post
delete
put
trace
options
head
connect
)Status Code
200 表示成功等Remote Address
请求的远程地址,转成ip
methods
:
HTTP1.0
定义了三种请求方法: GET
POST
HEAD
以及几种 additional request methods
:PUT
DELETE
LINK
UNLINK
HTTP1.1
定义了八种请求方法:get
post
delete
put
trace
options
head
connect
下面是常见的状态码
200
表示请求成功304
自上次请求,请求的资源没有发生过变化,请使用本地缓存400
客户端请求有错403
禁止访问,比如未登陆的情况下的返回码404
资源未找到500
服务器内部出错503
服务器不可用
常见的状态码范围
1xx
指示信息,表示请求已经接受,继续处理2xx
成功3xx
重定向,表示完成请求需要近一步操作4xx
客户端错误,请求有语法错误或者无法实现5xx
服务端错误,服务器未能完成合法请求
请求/响应头部
常用的请求头
Accept
接收类型,表示浏览器支持的MIME
类型,对表服务器返回的Content-Type
Accept-Encoding
浏览器支持的压缩类型,比如GZIP
,超出类型不支持Content-Type
客户端发出去的实体内容的类型Cache-Control
指定请求和响应遵守的缓存策略,比如no-cache
If-Modified-Since
对应服务器的Last-Modified
,用来匹配看文件是否修改了,精确到1s
,是http1.0
Expries
缓存控制,这个时间之前不会请求,直接使用缓存,http1.0
而且用的是服务器时间Max-age
代表缓存在本地多少秒,有效时间内不会请求,而是使用缓存,http1.1
If-None-Match
对应服务器的ETag
,用来匹配文件是否修改,非常准,http1.1
中Cookie
有Cookie
并且同域的时候会带上Connection
浏览器和服务器通信时对于长链接如何处理,keep-alive
Host
请求的服务器URL
Orgin
最初的请求从哪里来的,精确到端口,Origin
比Referer
更尊重隐私Referer
该页面的来源url
,适用于所有类型的请求,会精确到详细页面的地址,csrf
拦截常用这个User-Agent
用户的客户端信息
常用下响应头
Access-Control-Allow-Headers
服务器允许的请求头Access-Control-Allow-Methods
服务器允许的请求方法Access-Control-Allow-Origin
服务器允许的请求Origin
头部,比如*
Content-Type
服务器返回的实体内容类型Date
服务器发送的时间Cache-Control
告诉客户端什么情况下可以安全的缓存文档Last-Modified
最后的修改时间Expires
应该在什么时候认为文档过期了,从而不缓存Max-age
客户端本地应该缓存多久,开启了Cache-Control
后有效ETag
返回实体标签当前值Set-Cookie
设置和页面关联的Cookie
Keep-Alive
如果客户端有keep-alive
,服务器也会响应Server
服务器相关的信息
请求/响应实体
请求实体可以放类似 a=1&b=2
这样的序列化形式,也可以放表单 form data
对象,里面夹杂着文件等
响应实体就是服务端处理以后返回的信息
现在接口请求一般是 json
格式,而页面则是 html
文件,返回给浏览器解析
CRLF
Carriage-Return Line-Feed
,代表回车换行,作为分隔符
请求头和实体之间会有一个 CRLF
,响应头和响应实体也会有一个 CRLF
1
2
3
CRLF => Windows-style
LF => Unix Style
CR => Mac Style
cookie 优化
cookie
是浏览器的一种本地存储方式,帮助客户端和服务器通信,常用来验证身份,结合服务器的 Session
使用
- 用户登录
- 服务器生成一个
Session
,有用户的用户名等 - 会有一个
SessionId
,相当于服务器存储中的Key
- 服务器在登陆页面中写入
cookie
,比如jsessionid=xxx
- 浏览器本地有了这个,以后访问同域名下的网站都会带上
cookie
,有效时间内无需再次登陆,
加上 httpOnly
那么 js
无法访问了
也可以进行下面的优化,请求静态资源的时候也会加上 cookie
很浪费,可以把他们放在其他域名下
但是多域名拆分的话,因为域名解析很耗时间,会降低请求速度,我们一般使用 dns-prefetch
技术,让浏览器空闲的时候提前解析 dns域名
gzip 压缩
压缩格式,浏览器一般都支持,压缩效率很高,一般在 70%
,一般有 apache
tomcat
服务器开启
还有一些其他的压缩方法,比如 deflate
但是没有 gzip
流行和高效
所以一般都是服务器开启了 gzip
压缩
长连接和短连接
看下这两个在 tcp/ip
层的定义
- 长连接:一个
tcp/ip
上面可以连续发送多个数据包,在tcp
连接保持期间,如果没有数据包发送,需要双方发送检测包维持连接,需要自己做在线维持,比如心跳包 - 短连接:双方有数据交换的时候发起一个连接,发送结束以后就断开
在 http
层面
http1.0
默认都是短连接,每进行一次http
请求,建立一次连接,结束了就断开,比如每一个资源请求就发起一个单独的连接http1.1
开始默认用长连接,使用长连接会加上一个Connection: keep-alive
,在这种情况下网页打开以后服务器和客户端之间传输http
的tcp
连接不会断开,如果再次访问这个服务器的页面,会继续使用一条已经建立的连接
不过持续时间也是有限制的,一般在服务器进行配置,当然也需要客户端和服务器都支持
http2.0
下一代规范,说下和 http1.1
的区别
http1.1
中每请求一个资源需要开启一个tcp/ip
连接,对应的结果就是每个资源对应一个tcp/ip
连接,而tcp/ip
本身有并发限制,当资源多的时候就慢下来了http2.0
中一个tcp/ip
连接可以请求多个资源,只要一次tcp/ip
请求可以返回多个资源,分割成更小的帧请求,速度更加快
所以如果 http2.0
全面应用,http1.1
里面的一些优化方法就没必要了,比如打包成精灵图,静态资源多域名拆分等
- 多路复用,一个
tcp/ip
可以请求多个资源 - 首部压缩,
http
头部压缩,减小体积 - 二进制分帧,在应用层和传输层之间加了一个二进制分帧层,改进传输性能,实现低延迟和高吞吐
- 服务器推送,服务器可以对客户端的一个请求发出多个响应,也可以主动通知客户端
- 请求优先级,如果流被赋予了优先级,会基于这个优先级处理,由服务器决定需要多少的资源来处理这个请求
https
在请求前,会建立 ssl
,确保接下来的请求都是加密的,无法轻易截取分析
要把网站升级成 https
需要后端支持,申请证书什么的
而由于需要建立额外的安全连接和加密等,开销也会更加大
下面我们关心下 SSL/TLS
握手过程
- 浏览器请求一个
SSL
连接,并向服务器发送一个随机数client random
和客户端支持的加密方法,比如rsa
加密,这个是明文传输的 - 服务器从中选出一组加密算法和
hash
算法,回复一个随机数server random
,并把自己的身份信息以证书的方法返回给客户端(证书包含了服务器的网站地址,非对称加密的公钥,证件颁发机构等信息) - 浏览器收到了服务器的证书以后
- 验证证书的合法性(颁发的结构是否合法,包含的地址和访问的地址是否一致),如果可信的会有一个绿色的小锁头
- 用户接收到证书以后,会产生一个新的随机数
Premaster secret
,证书中的公钥和指定的加密方法加密Premaster secret
,发送给服务器 - 利用
client random
server random
Premaster secret
通过一定的算法生成http
连接传输的对称加密key
-session key
- 使用约定好的
hash
算法计算握手信息,并且使用生成的session key
对信息进行加密,然后把之前算出来的所有信息返回给服务器
- 服务器接收到了浏览器的信息
- 利用已知的加解密算法和自己的私钥进行解密,获得
Premaster secret
- 和浏览器一样的规则生成
session key
- 使用
session key
解密浏览器发来的握手信息,验证hash
和浏览器发过来的是不是一致 - 使用
session key
加密一段握手信息给浏览器
- 利用已知的加解密算法和自己的私钥进行解密,获得
- 浏览器解密和计算握手信息的
hash
,如果和服务器发过来的一样,握手结束
之后所有的 http
请求,使用前面的 session key
进行对称加密算法加密