从输入URL到页面加载的过程(5) - 后台和前台的 http 交互

Posted by cody1991 on July 25, 2020

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 methodsPUT 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
  • CookieCookie 并且同域的时候会带上
  • Connection 浏览器和服务器通信时对于长链接如何处理,keep-alive
  • Host 请求的服务器 URL
  • Orgin 最初的请求从哪里来的,精确到端口,OriginReferer 更尊重隐私
  • 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 是浏览器的一种本地存储方式,帮助客户端和服务器通信,常用来验证身份,结合服务器的 Session 使用

  1. 用户登录
  2. 服务器生成一个 Session,有用户的用户名等
  3. 会有一个 SessionId,相当于服务器存储中的 Key
  4. 服务器在登陆页面中写入 cookie,比如 jsessionid=xxx
  5. 浏览器本地有了这个,以后访问同域名下的网站都会带上 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,在这种情况下网页打开以后服务器和客户端之间传输 httptcp 连接不会断开,如果再次访问这个服务器的页面,会继续使用一条已经建立的连接

不过持续时间也是有限制的,一般在服务器进行配置,当然也需要客户端和服务器都支持

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 握手过程

  1. 浏览器请求一个 SSL 连接,并向服务器发送一个随机数 client random 和客户端支持的加密方法,比如 rsa 加密,这个是明文传输的
  2. 服务器从中选出一组加密算法和 hash 算法,回复一个随机数 server random,并把自己的身份信息以证书的方法返回给客户端(证书包含了服务器的网站地址,非对称加密的公钥,证件颁发机构等信息)
  3. 浏览器收到了服务器的证书以后
    1. 验证证书的合法性(颁发的结构是否合法,包含的地址和访问的地址是否一致),如果可信的会有一个绿色的小锁头
    2. 用户接收到证书以后,会产生一个新的随机数 Premaster secret,证书中的公钥和指定的加密方法加密 Premaster secret,发送给服务器
    3. 利用 client random server random Premaster secret 通过一定的算法生成 http 连接传输的对称加密 key - session key
    4. 使用约定好的 hash 算法计算握手信息,并且使用生成的 session key 对信息进行加密,然后把之前算出来的所有信息返回给服务器
  4. 服务器接收到了浏览器的信息
    1. 利用已知的加解密算法和自己的私钥进行解密,获得 Premaster secret
    2. 和浏览器一样的规则生成 session key
    3. 使用 session key 解密浏览器发来的握手信息,验证 hash 和浏览器发过来的是不是一致
    4. 使用 session key 加密一段握手信息给浏览器
  5. 浏览器解密和计算握手信息的 hash,如果和服务器发过来的一样,握手结束

之后所有的 http 请求,使用前面的 session key 进行对称加密算法加密

SSL/TLS握手