HTTP使用指南 | 青训营笔记

115 阅读13分钟

这是我参与「第四届青训营 」笔记创作活动的的第12天

前言

通过这篇文章我们可以了解到:

  1. 什么是HTTP协议,基本特点是什么?
  2. HTTP协议的报文结构,发展历程
  3. 常见场景的分析:静态资源、登录
  4. HTTP协议在浏览器与node中的使用
  5. 了解一些其他的协议

1. 初识HTTP

首先思考一个问题我们在浏览器中输入一个网址是浏览器是如何呈现给我们一个右侧的网站呢?

来看一下这张图的,首先用户输入网址,然后brower进程处理输入信息后,交给brower内核向服务器发起网络请求,服务器返回响应内容,内核读取响应,然后进行渲染页面,页面加载完成。

我们今天主要学习的是OSI七层网络模型中的Application应用层中的HTTP协议。

什么是HTTP

HTTP全称为 Hyper Text Transfer Protocol 超文本传输协议,是一个用于传输超文本文档的应用层协议,它是为Web浏览器与Web服务器之间的通信而设计的。

  • 主要帮我们传输一些HTMLCSSJavaScript内容
  • 应用层协议,基于TCP协议
  • 请求 响应
  • 简单可扩展:语义简单且可在请求头自定义内容
  • 无状态:请求之间是孤立的

2. HTTP协议分析

2.1. HTTP协议发展历程

HTTP协议到目前为止全部的版本可以分为HTTP 0.9HTTP 1.0HTTP 1.1HTTP 2.0HTTP 3.0,其中现在普遍应用的版本是HTTP 1.1版本,正在推进HTTP 2.0版本,以及未来的HTTP 3.0版本。


HTTP 0.9

HTTP 0.9也被称为单行协议,最初版本的HTTP协议并没有版本号,后来它的版本号被定位在0.9 以区分后来的版本,HTTP 0.9极其简单,请求由单行指令构成,以唯一可用方法GET开头,其后跟目标资源的路径。HTTP 0.9的响应内容并不包含HTTP头,这意味着只有HTML文件可以传送,无法传输其他类型的文件,也没有状态码或错误代码,出现异常时一个特殊的包含问题描述信息的HTML文件将被响应返回。

特点

  • 只有一个请求行,并没有HTTP请求头和请求体。
  • 服务器没有返回头信息,只返回数据信息。
  • 第三个是返回的文件内容是以ASCII 字符流来传输的,因为都是HTML 格式的文件,所以使用ASCII 字节码来传输是最合适的。

HTTP 1.0

HTTP 1.0构建了可扩展性,为了满足传输多种类型文件的需求,为了让客户端和服务器能更深入地交流,HTTP 1.0引入了请求头和响应头,它们都是以为Key-Value形式保存的,在HTTP发送请求时,会带上请求头信息,服务器返回数据时,会先返回响应头信息。

特点

  • 协议版本信息会随着每个请求发送,即HTTP 1.0被追加到了GET行。
  • 引入请求头,在发起请求时候会通过HTTP请求头告诉服务器它期待服务器返回什么类型的文件、采取什么形式的压缩、提供什么语言的文件以及文件的具体编码。
  • 引入响应头,服务器以请求头中信息准备数据,并以响应头的信息告诉客户端数据采用何种格式返回,倘若遇到不支持的格式,只能返回服务器支持的格式,并在响应头中体现,也就是说最终浏览器是以响应头的信息解析数据。
  • 引入状态码,状态码会在响应开始时发送,使浏览器能了解请求执行成功或失败,并相应调整行为。
  • 引入了缓存机制,通过状态码与If-Modified-SinceExpires等控制更新或使用本地缓存。
  • 引入了Content-Type头,使HTTP具备了传输除纯文本HTML文件以外其他类型文档的能力。

HTTP 1.1

HTTP 1.1是标准化的协议,HTTP 1.1消除了大量歧义内容并引入了多项改进。

特点

  • 缓存处理,HTTP 1.1引入了更多的缓存控制策略,例如Entity tagIf-Unmodified-SinceIf-MatchIf-None-Match等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化以及网络连接的使用,在请求头中引入了range,它允许只请求资源的某一个部分,即返回206状态码,这样方便了开发者自由选择以便充分利用带宽和链接,并且可以使用RangeContent-Range制作断点续传功能。
  • 错误通知的管理,在HTTP 1.1中新增了24个错误状态码。
  • 增加Host请求头,能够使不同域名配置在同一个IP地址的服务器上。
  • 支持长连接,HTTP 1.1支持长连接,在一个TCP连接上可以传输多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP 1.1中默认开启Connection:keep-alive,一般浏览器对于同一个域名允许同时建立6个长链接。
  • 增加管线化技术,允许在第一个应答被完全发送之前就发送第二个请求,以改善队头阻塞问题,但响应的顺序还是会按照请求的顺序返回。
  • 支持响应分块,通过设置Transfer-Encoding: chunked进行分块响应,允许响应的数据可以分成多个部分,配合服务端尽早释放缓冲可以获得更快的响应速度。

HTTP 2.0

HTTP 2.0拥有更优异的表现,现网页愈渐变得的复杂,甚至演变成了独有的应用,媒体的播放量,增进交互的脚本大小也增加了许多,更多的数据通过HTTP请求被传输,由此HTTP 2.0为网络效率做了大量的优化。

特点

二进制分帧,HTTP 2.0是二进制协议而不是文本协议,将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码。

  • 多路复用,并行的请求能在同一个链接中处理,在同一域名下所有访问都是从同一个TCP连接中走,HTTP消息被分解为独立的帧,服务端根据标识符和首部将消息重新组装起来,移除了HTTP 1.1中顺序和阻塞的约束。
  • 压缩headerheader在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本。
  • 服务端推送,服务器可以主动地向客户端推送资源,而无需客户端明确的请求。

HTTP 3.0

HTTP 3.0目前处于制订和测试阶段,是未来的全新的HTTP协议,HTTP 3.0协议运行在QUIC协议之上,是在UDP的基础上实现了可靠传输,权衡传输速度与传输可靠性并加以优化,使用UDP将避免TCP的队头阻塞问题,并加快网络传输速度,但同样需要实现可靠传输的机制,HTTP 3.0不是HTTP 2.0的拓展,HTTP 3.0将会是一个全新的协议。

2.2. 协议分析-报文

以HTTP/1.1为例

1. 先看一个完整的HTTP请求

2. 再看头部的一些具体字段的含义

Method 请求方法

HTTP请求的特点(我们应该遵守的特性):

  • Safe(安全的):不会修改服务器数据的方法都是安全的,如GET HEAD OPTIONS
  • Idempotent(幂等):同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的,所有安全的方法都是幂等的;除此之外,PUTDELETE也是幂等的。

StatusCode 状态码

RESTful API

RESTful API是一种API设计风格;REST-Representational State Transfer

  1. 每一个URI代表一种资源:
  2. 客户端和服务器之间,传递这种资源的某种表现层;
  3. 客户端通过HTTP method,对服务器端资源进行操作,实现"表现层状态转化"。

常用的请求头

常用响应头

缓存相关的分析

缓存分为强缓存和协商缓存:

  • 强缓存是指本地有这个请求的缓存就直接用了
  • 协商缓存是指本地有缓存,这个缓存能不能用,需要跟服务器进行协商,才能确认。

强缓存和协商缓存的一些请求头/响应头字段

缓存的处理流程

Cookie

来看一下响应中Set-Cookie字段


HTTP/2概述

HTTP/2为什么更快、更稳定、更简单

HTTP/2协议的基本概念:

  • 帧(frame):HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流。
  • 采用二进制编码发送

HTTP/1.xHTTP/2的对比

  • HTTP/1.x 采用文本形式发送,而HTTP/2采用二进制编码,且将每个块划分为独立的帧。

消息:与逻辑请求或响应消息对应的完整的一系列帧。 数据流:已建立的连接内的双向字节流可以承载一条或多条消息。

帧之间交错发送(无序),接收方进行重组织即可

HTTP/2特点:

  • HTTP/2 连接都是永久的,而且仅需要每个来源一个连接
  • 流控制:阻止发送方向接收方(服务器)发送大量数据的机制
  • 服务器可主动推送信息

当浏览器请求一个页面page.html时,服务器发现该页面引用了一些外部资源jscss,然后服务器就主动推送这些外部资源。


HTTPS概述

HTTPS 全称为 Hypertext Transfer Protocol Secure,经过TSL/SSL加密,使用的是非对称加密。

对称加密和非对称加密:

  • 对称加密:加密和解密都是使用同一个密钥
  • 非对称加密,加密和解密需要使用两个不同的密钥:公钥(public key)和私钥(private key)

3. 场景分析

3.1. 场景分析-静态资源 缓存

首先打开浏览器,输入www.toutiao.com,打开控制台,右键进行检查,切换到network 状态码200一定发起了请求吗? 我们仔细看可以发现,200请求是从缓存中取出的,没有发起真正的请求。然后我们分析一下缓存策略:

  • cache-control看出是强缓存,缓存期限为一年
  • content-type可以看出是CSS资源
  • access-control-allow-origin: * 可以看出允许所有域名进行访问

静态资源部署方案

我们通常使用的方案是缓存+CDN+文件名hash

当用户首次访问我们的网站的时候,由于没有缓存,需要进行静态资源的请求,那么如何更快的获取静态资源,来提升用户的体验呢? 那么我们可以把静态资源放到CDN上,CDN 全称为Content Delivery Network:通过用户就近性和服务器负载的判断,CDN确保内容以一种极为高效的方式为用户的请求提供服务。

CDN是一种内容分发网络,可以根据用户位置,分析出最近的资源,进行返回,提升网站加载速度。 我们用了缓存,而且是强缓存,有效期是一年,如果我们改动了静态资源,那么我们如何保证资源是最新的呢?

一本是对请求的资源文件名,加上文件名hash,每次请求资源的时候,hash值都会变化,文件名变化,对应不上缓存中的文件名,就会请求新的资源。

3.2. 场景分析-登录

业务场景:表单登录,扫码登录

技术方式:SSO单点登录

首先我们进行账号密码登录,然后打开控制台-network-勾选preserve log-过滤quick_login,观察请求。 我们会看到有两个请求,这两个请求有什么区别? 首先是请求方法不同:OPTIONSPOST

为什么会有OPTIONS请求?

由于请求地址与网站地址不同,产生了跨域(协议不同,域名不同,端口号不同),跨域的请求需要进行处理,通过CORS进行跨域资源的处理:

  1. 首先进行预请求OPTIONS,获取服务端是否允许该跨源请求(复杂请求)
  2. 如果允许该跨源请求就开始真正的请求POST

跨域请求的解决方案

  • CORS
  • 代理服务器
  • Iframe不推荐

代理服务器是通过架设一台同域的服务器,接收浏览器的请求,再转发给真正的服务器

真正的POST请求

真正的请求向什么地址做了什么动作?

  • 使用POST方法
  • 目标域名https:/sso.toutiao.com
  • 目标path/quick_.login/v2/

携带了那些信息,返回了那些信息?

  • 携带信息

    • Post body,数据格式为form
    • 希望获取的数据格式为json
    • 已有的cookie
  • 返回信息

    • 数据格式json
    • cookie的信息

下一次进入页面为什么能记住登录态呢?

这就涉及到鉴权了,有两种方式:

  • Session + Cookie
  • JWT (JSON web token)

Session + Cookie 首先是我们进行登录,把账号密码提交给服务器。服务器进行验证,如果正确,服务器生成Session,保存用户信息,然后通过set-cookie返回用户信息,用户进行登录。下一次请求自动携带之前的Cookie,然后服务器根据Session对携带的Cookie信息进行验证,验证成功返回信息。

JWT 首先是我们进行登录,把账号密码提交给服务器。服务器进行验证,如果正确,根据用信息生成token,直接返回给浏览器,不进行存储。浏览器进行下一次请求的时候,设置请求头,携带token,服务器解析token,如果解析出的用户信息正确,就返回信息。

SSO单点登录 我们点击右上角-发文章,跳转后的网站为什么自动登录,而不进行再登录呢? 这就需要了解一下SSO(单点登录 Single Sign On)了。

4. 实战

4.1. 请求篇

浏览器发起请求

通过XHR: XMLHttpRequest

通过fetch

  • XMLHttpRequest的升级版,使用Promise,解决回调地狱问题
  • 模块化设计,esponseRequestHeader对象
  • 通过数据流处理对象,支持分块读取

node.js发起请求,

通过标准库:HTTP/HTTPS

  • 默认模块,无需安装其他依赖
  • 功能有限/不是十分友好

当然上述的浏览器,node发起请求较为麻烦,我们可以请求库来解决:

常用的请求库:axios

  • 支持浏览器、nodejs环境
  • 具有丰富的拦截器

4.2. 用户体验篇

网络优化

稳定性

重试是保证稳定的有效手段,但要防止加剧恶劣情况 缓存合理使用,作为最后一道防线

5. 了解更多

WebSocket

  • 浏览器与服务器进行全双工通讯的网络技术
  • 典型场景:实时性要求高,例如聊天室
  • URL使用WS:/WSS:/等开头

QUIC:Quick UDP Internet Connection

  • O-RTT建联(首次建联除外)。
  • 类似TCP的可靠传输。
  • 类似TLS的加密传输,支持完美前向安全。
  • 用户空间的拥塞控制,最新的BBR算法。
  • 支持h2的基于流的多路复用,但没有TCPHOL问题。
  • 前向纠错FEC
  • 类似MPTCP的Connection migration

TCPQUIC的响应速度对比

6. 参考资源