浏览器发起 HTTP 请求的典型场景
我们通过上面这张图来解释一下浏览器是如何发起一个 HTTP 请求的。
先来看上图左边部分,我们浏览的网页通常会有多种文件类型,除了 html 文件,还会有 css/jpg/png/mp4 等等其他的文件类型。那么当我们输入一个网址的时候,浏览器会做哪些操作呢?
我们通过右边这张图来做一个解释。
- 首先用户打开浏览器,这个时候呈现出来的就是一个用户界面;
- 用户在地址栏输入网址,这个时候可能网址还没有输入完,浏览器就已经自动联想出来了,这是因为之前已经输入过了这个网址,浏览器从数据库中自动搜索出来了这个网址;
- 然后浏览器引擎通过操作渲染引擎发出网络请求,这个时候还要涉及到 DNS 解析等过程,返回来的第一个页面中,可能还会包含 JS 文件,或者其他的文件,渲染引擎通过 JS 解释器执行 JS,并重新发起请求获取其他的文件;
- 最终,渲染引擎将返回来的所有的文件通过 UI 后端绘制出来,展示在用户界面上。
通过以上的几个步骤,浏览器就实现了一个 HTTP 请求,并将请求页面展示在我们面前,我们就看到了想要访问的页面。
上图是一个更加详细的请求过程。
- 首先浏览器会从 URL 中解析出域名,服务器在 80 或 443 端口进行监听;
- 然后浏览器根据域名查询 DNS,获取到域名对应的 IP 地址;
- 接着浏览器通过三次握手建立 TCP 连接,如果是 HTTPS 的话还要完成 TLS/SSL 握手;
- 浏览器构造 HTTP 请求,填充上下文到 HTTP 头部中;
- 浏览器发起 HTTP 请求,接收服务器返回的携带 HTML 页面包体的 HTTP 响应;
- 浏览器引擎解析响应,渲染包体到用户界面,根据页面的超链接构造其他的 HTTP 请求;
- 浏览器发送获取页面内其他资源的 HTTP 请求。
以上就是一个详细的 HTTP 请求的过程。
HTTP 协议是一个无状态的、应用层的、以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动。
这个定义里面有几个重点:
- 无状态:HTTP 协议请求之间是没有关联的,每个请求之间不依赖其他请求的状态
- 请求/应答:HTTP 协议必须基于一个连接,HTTP 协议才能在这个连接上响应请求
- 可扩展的语义:这个意思是说 HTTP 协议的头部字段是可以扩展的
- 自描述:这里的意思是说通过传递的消息我们就可以知道传递的是视频、音频还是文本
- 超文本信息:是指传递的消息不只是文本,还有音频、视频等大粒度的内容
HTTP 协议的格式
ABNF
ABNF 是扩充巴科斯-瑙尔范式,是用来定义协议规范的一种格式,rfc 文档地址:https://www.ietf.org/rfc/rfc5234.txt,核心规则如下:
ABNF 的操作符如下:
空白字符:用来分隔定义中的各个元素
- method SP request-target SP HTTP-version CRLF
选择 / :表示多个规则都是可供选择的规则
- start-line = request-line / status-line
值范围 %c##-##:
- OCTAL = “0” / “1” / “2” / “3” / “4” / “5” / “6” / “7” 与 OCTAL = %x30-37 等价
序列组合 ():将规则组合起来,视为单个元素
不定量重复m*n
* 元素表示零个或更多元素:*( header-field CRLF )
1* 元素表示一个或更多元素,2*4 元素表示两个至四个元素
可选序列 []:
- [ message-body ]