这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
HTTP 协议是前后端接触过最多的协议,在系统学习 HTTP协议 此之前,我只是了解如何用代码层次去实现请求数据,虽然知道一些基本概念,但是深一点的知识就不懂了,这次课程也带我重新认识了 HTTP 协议还有其他协议。如果只是停留在代码层次,那么就和一个码农差不多了,所以以后也要深入研究一下其他深一点的技术知识。
1. 初识 HTTP
Web 页面不能凭空显示出来。根据Web浏览地址栏中指定的 URL,Web浏览器从 Web 服务器端获取文件资源(resource)等信息,从而显示出Web页面。
像这种通过发送请求获取服务器资源的 Web浏览器等,都可称为客户端(client)
Web使用一种名为HTTP(HyperText Tranfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器一系列运作流程。而协议是制定规则的约定。可以说,Web是建立在HTTP协议上通信的。

1.1 什么是 HTTP
HTTP:Hyper Text Transfer Protocol(超文本传输协议)
特点:
- 应用层协议,基于 TCP 协议
- 请求响应
- 简单可扩展
- 无状态:每一次请求都是孤立的,当前的请求并不知道之前请求的数据
1.2 发展
| HTTP版本 | 特点 | 新增 |
|---|---|---|
| HTTP/0.9 | 单行协议 | 请求 GET/mypage.html,只有 HTML 文档 |
| HTTP/1.0 | 构建可扩展性 | 增加了 Header、状态码并支持多种文档类型 |
| HTTP/1.1 | 标准化协议 | 链接复用、缓存、内容协商 |
| HTTP/2 | 更优异的表现 | 二进制协议、压缩 header、服务器推送 |
| HTTP/3 | 草案 |
1.3 报文
HTTP/1.1
| 请求方法 | |
|---|---|
| GET | 请求一个指定资源,使用 GET 应只被用于获取数据 |
| POST | 将实体提交到指定的资源(如用户信息),通常导致服务器上的状态变化或副作用 |
| PUT | 替换目标资源(修改密码) |
| DELETE | 删除指定的资源(注销账号) |
| HEAD | 请求一个与 GET 请求的响应相同的响应,但没有响应体 |
| CONNECT | 建立一个由目标资源标识的服务器隧道 |
| OPTIONS | 用于描述目标资源的通信选项 |
| TRACE | 沿着到目标资源的路径执行一个消息环回测试 |
| PATCH | 用于对资源应用部分修改 |
注:虽然 GET、POST 等都可以实现某些功能,但是请根据语义化使用,
不会修改服务器数据的方法是 Safe(安全的),如 GET、HEAD、OPTIONS
同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的,所有 safe 的方法 都是 idmponent(幂等) 的,如 GET、HEAD、OPTIONS、PUT、DELETE
例如:
GET www.xxx.com/api/user # 获取用户
POST www.xxx.com/api/user # 创建用户
PUT www.xxx.com/api/user/{id} # 修改用户信息
DELETE www.xxx.com/api/user/{id} # 删除用户信息
1.3 状态码
| 状态码 | 类别 | 原因短语 |
|---|---|---|
| 1XX | Informational(信息性状态码) | 接收的请求正在处理 |
| 2XX | Success(成功状态码) | 请求正常处理完毕 |
| 3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
| 4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
| 5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
常见的状态码
- 200:表示从客户端发来的请求在服务器端被正常处理了
- 204:请求成功,但没有资源可以反悔
- 206:表示客户端进行了范围请求,而服务器成功执行了这部分 GET 请求。响应报文中包含由 Content-Page 指定范围的实体内容
- 301:永久重定向
- 302:临时重定向
- 303:与 302 类似,但是 303 状态码明确表示客户端应该用 GET 方法获取资源
- 304:客户端发送附带条件的请求,服务器允许请求访问资源,但是未能满足条件,不包含任何响应主体部分。虽然是 3XX 但是跟重定向无关
- 307:临时重定向:与 302 有着相同的含义。302 标准禁止 POST 变换成 GET,但实际大家并不遵守。307 会遵照浏览器标准,不会从 POST 变成 GET(每个浏览器可能存在不同情况)
- 400:请求报文含有语法错误
- 401:没有进行权限认证
- 403:请求资源的访问被服务器拒绝了
- 404:服务器无法找到请求的资源
- 500:服务端执行请求发生了错误
- 503:服务器暂时处于超负载或者正在停机维护
常用请求头
| 名字 | 作用 |
|---|---|
| Accept | 接受类型,表示浏览器支持的 MIME 类型(服务端中的 Content-Type) |
| Content-Type | 客户端发送出去实体内容的类型 |
| Cache-Control | 指定请求的响应遵循的缓存机制,如 no-cache |
| If-Modified-Since | 用来匹配看文件是否变动,只能精确到1s之内(服务单的 Last-Modified) |
| Expires | 缓存控制,这个时间内不会请求,直接使用缓存,服务端时间 |
| Max-age | 标示资源在本地缓存多少秒 |
| If-None-match | 用来匹配文件内容是否改变,非常精确(服务端的ETag) |
| Cookie | 有cookie并且同域访问时会自动带上 |
| Referer | 该页面的来源 URL(适用于所有类型的请求,会精确到详细页面地址,csrf 拦截常用到这个字段) |
| Origin | 最初的请求是从哪里发起的(只会精确到端口),比 Referer 更尊重隐私 |
| User-Agent | 用户客户端的一些必要信息,如 UA 头部等 |
常用响应头
| 名字 | 作用 |
|---|---|
| Content-Type | 服务端返回的实体内容的类型 |
| Cache-Control | 指定请求和响应遵循的缓存机制,如no-cache |
| Last-Modified | 请求资源的最后修改时间 |
| Expires | 应该在什么时候认为文档已经过期,从而不再缓存它 |
| Max-age | 客户端的本地资源应该缓存多少秒,开启了Cache-Control后有效 |
| ETag | 资源的特定版本的标识符,Etags类似于指纹 |
| Set-Cookie | 设置和页面关联的cookie,服务器通过这个头部把cookie传给客户端 |
| Server | 服务器的一些相关信息 |
| Access-Control-Allow-Origin | 服务器端允许的请求Origin头部(譬如为*) |
cookie
set-Cookie-response
| 内容 | 作用 |
|---|---|
| Name=value | 各种cookie的名称和值 |
| Expires=Date | Cookie的有效期,缺省时Cookie仅在浏览器关闭之前有效。 |
| Path=Path | 限制指定Cookie的发送范围的文件目录,默认为当前 |
| Domain=domain | 限制cookie生效的域名,默认为创建cookie的服务域名 |
| secure | 仅在HTTPS安全连接时,才可以发送Cookie |
| HttpOnly | JavaScript脚本无法获得Cookie |
| SameSite=[None][Strict][None] | 同站、跨站请求都可发送Strict仅在同站发送,允许与顶级导航一起发送,并将与第三方网站发起的GET请求一起发送 |
1.4 HTTP/2
帧(frame) :HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标示出当前帧所属的数据流
消息:与逻辑请求或响应消息对应的完整的一系列帧
数据流:已建立的连接内的双向字节流,可以承载一条或多条信息
帧可以交错发送、接收方再重组织
HTTP/2 连接都是永久的,而且仅需要每个来源一个连接
流控制:阻止发送方向接收方发送大量数据的机制
1.5 HTTPS
HTTPS:Hypertext Transfer Protocol Secure
见过 TSL/SSL 加密
对称加密:加密和解密都是使用同一个密钥
非对称加密:加密和解密需要使用两个不同的密钥:公钥(public key)和私钥(private key)
2. HTTP 协议应用场景分析
2.1 以今日头条为例分析
200 的请求一定发送请求了吗?
从图中看到,是从本地缓存获取的 css 文件
强缓存:Cache-control: max-age=2592000
允许所有域名访问:access-control-allow-origin: *
请求资源为CSS类型:content-type: text/css; charset=utf-8
2.2 静态资源优化
静态资源方案:
缓存 + CDN + 文件名 hash
CDN:Content Deliver Network(用户分发网络)。通过用户就近性和服务器负载的判断,CDN 确保内容以一种极为高效的方式为用户的请求提供服务
2.3 场景分析-登录
域的构成:scheme、host name、port
当域构成部分任何一点不同,就会存在跨域问题
解决跨域请求:CORS(Cross-Origin Resource Sharing)、代理服务器(同源策略是浏览器的安全策略,不是 HTTP 的)、Iframe(不便)
预请求:获知服务端是否允许该跨域请求(复杂请求)
相关协议头:
- Access-Control-Allow-Origin
- Access-Control-Expose-Headers
- Access-Control-Max-Age
- Access-Control-Allow-Credentials
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Request-Method
- Access-Control-Request-Headers
当我们登陆之后,刷新页面也能记住我们的登录状态,这就使用了鉴权方案
鉴权方案:Seesion + cookie、JWT(JSON web token)
3. 实战篇
浏览器内置了 XHR: XMLHttpRequest,不过这个太麻烦了,一般我会用 Fetch
node 中也会有 HTTP/HTTPS 模块
axios:支持浏览器、nodejs 环境;丰富的拦截器
这些东西以后我也会记笔记更新。
3.1 稳定性
稳定性可以从重试机制(超时、错误)、缓存、数据安全(HTTPS、劫持) 考略,但注意的是重试虽然是保证稳定的手段,但要防止加剧恶劣情况。
缓存作为稳定性的最后一道防线
3.1 WebSocket
浏览器与服务器进行全双工通信的网络技术
电影场景:实时性要求高,例如聊天室
URL 使用 ws:// 或 wss:// 等开头
3.2 QUIC: Quick UDP Internet Connect
HTTP3 草案的一部分
0-RTT建联(首次建联除外)。
类似TCP的可靠传输。
类似TLS的加密传输,支持完美前向安全。
用户空间的拥塞控制,最新的BBR算法。
支持h2的基于流的多路复用,但没有TCP的HOL问题。
前向纠错FEC。
类似MPTCP的Connection migration。