# HTTP 协议
超文本传输协议(HyperText Transfer Protocol)是万维网中非常重要的基础,作为应用层协议,承担起了网络数据通信的绝大部分工作。
# 特点
- 简单:基于
请求-响应
的模式,发起请求时只需指定请求方法(GET、POST)和路径 - 灵活:支持不同格式的数据传输,具有非常多的可选字段
- 无连接:每次连接只处理一个请求,降低资源消耗,可以同时服务多个客户端
- 无状态:对事物处理无记忆能力,前一次请求和后一次没有相连关系,从而可以更快的应答
# 工作简要流程
- 在发送 HTTP 请求之前,我们先建立 TCP 连接(三次握手)
- 通过 TCP 套接字,客户端将 HTTP 请求发送给服务端,默认的 http 端口为 80
- 服务端收到请求后进行解析,处理后将结果通过 TCP 套接字返还给客户端
- 客户端收到数据后进行解析,将不同的内容以不同的形式进行显示或使用
- 根据 connection 模式的不同,服务端会主动关闭 TCP 连接,或者维持该连接一段时间。
# 请求方法
HTTP/1.1 定义了八种方法以不同方式操作指定的资源:
方法 | 作用 |
---|---|
GET | 向指定资源发出获取请求。GET 应只用在读取数据上 |
HEAD | 与 GET 类似,只保留 HTTP Header 不保留 Body,得到必要信息的同时节约带宽 |
POST | 向指定资源提交数据,请求服务器进行处理 |
PUT | 向指定资源位置上传其最新内容 |
DELETE | 请求服务器删除 Request-URI 所标识的资源 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
OPTIONS | 返回该资源所支持的所有 HTTP 方法 |
CONNECT | 用于代理服务器,让代理服务器代替用户去获取其他网页 |
其中,我们一般用户用的最多的就是 GET 请求与 POST 请求。
对于 GET、HEAD、POST 这三种请求,如果:
- 没有添加自定义头(比如 token、Authentication)
Content-Type
为text/plain
、multipart/form-data
、application/x-www-form-urlencoded
其中一种
该请求则被视为简单请求。
而其他的请求(一般以 ajax 请求形式)就属于非简单请求了。
# GET 与 POST 的区别
方面 | GET | POST |
---|---|---|
定义 | 从指定的资源请求数据 | 向指定的资源提交要被处理的数据 |
用途 | 一般用于获取资源,不应该去修改资源 | 更多用于提交表单,处理敏感数据 |
提交数据 | 将附带的数据以键值对的形式加在 URL 末尾实现的(以? 开头),有数据长度的限制 | 将附带的数据以键值对的形式加在 HTTP Body 中发送,对数据长度没有要求 |
缓存 | 能够被浏览器缓存,可以存为书签、有历史记录 | 不行 |
安全 | 请求的数据暴露在 URL 中,任何人都能看到,安全性较差 | 请求数据不显示于 URL,且不会被浏览器或服务器缓存,安全性相对较好 |
幂等 | 我们一般要求它符合幂等性 | 一般不具幂等性 |
幂等性即多次操作与单次操作得到的结果都是相同的,好似“1 的三次方仍然等于 1”一样。
# 状态码
状态码 | 类别 | 解释 |
---|---|---|
1XX | Informational(信息) | 接收的请求正在处理 |
2XX | Success(成功) | 请求正常处理完毕 |
3XX | Redirection(重定向) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误) | 服务器无法处理请求 |
5XX | Server Error(服务器错误) | 服务器处理请求出错 |
常见的一些状态码:
状态码 | 类别 | 解释 |
---|---|---|
200 | OK | 客户端请求成功 |
301 | Moved Permanently | 永久重定向。浏览器会自动定向到返回信息里的新 URI |
302 | Found | 临时重定向。与 301 类似,但资源只是临时被移动 |
304 | Not Modified | 所请求的资源未修改,可以复用协商缓存 |
400 | Bad Request | 客户端请求有语法错误,不能被服务器所理解 |
401 | Unauthorized | 请求未经授权,请求要求用户身份认证 |
403 | Forbidden | 服务器收到请求,但是拒绝提供服务 |
404 | Not Found | 请求资源不存在(如输入了错误的 URL) |
500 | Internal Server Error | 服务器内部发生不可预期的错误 |
503 | Server Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求 |
# 版本
比较常提到的 HTTP 协议版本一般有 1.0、1.1、2.0。
# HTTP/1.0
HTTP/1.0 在设计时,为了提高服务器系统的响应效率,规定浏览器与服务器只保持短暂的连接,每次 HTTP 请求都要与服务器建立一次 TCP 连接,并在请求结束后断开该连接。
但随着网络的发展,网页变得越来越复杂,很快 HTTP/1.0 就更不上时代了。因为对于一个网页,客户端往往需要多次请求才能完整地显示它(比如存在图片等其他资源),而 TCP 连接的无法复用使得每次 HTTP 请求都得经历三次握手、慢启动的过程,反而使开销增大。
于是很快,HTTP/1.1 版本出现了。
# HTTP/1.1
HTTP/1.1 很大的一个特点就是支持持久连接(且为默认值)。在一个 TCP 连接上我们可以多次发起 HTTP 请求并得到响应,减少了建立和关闭连接的消耗和延迟。
在 HTTP/1.1 中,我们使用 Connection
请求头字段作为连接的持久性的设置。使用 keep-alive
则为默认的长连接,而 close
则表明自己并不想维持长连接。
除此以外,HTTP/1.1 还增加了一些其他功能:
- Cache 缓存使用
ETag
与If-None-Match
的新字段,解决了旧字段的误差、精度、性能问题 Host
请求头字段,允许服务器在相同 ip 地址与端口号的情况下配置不同的 web 站点- 通过指定
RANGE:bytes=XXXX
,实现文件从 XXXX Bytes 开始的断点续传 - ...
# HTTP/2.0
HTTP/1.1 在各方面而言做的都还不错,所以一直没有推出新版本。不过随着网络的继续发展,我们开始更加关注 HTTP 协议的性能,想要在其中取得更加好的效果。
我们能够发现 HTTP/1.1 有着这些缺点:
- 虽然 1.1 通过管道技术实现一次性发送多个请求,但如果出现队头阻塞(即第一个请求阻塞),后面的请求也得跟着等待
- 只能由客户端单向发起请求
- 无记忆性使得报文头信息冗余量大
- 通过文本传输,数据未压缩
于是 HTTP/2.0 针对性能提出了几个优化特性:
# 二进制分帧
原来的纯文本传输非常的直白简单,但是由于文本的多样性,在解析和拓展上比较麻烦。而 HTTP/2.0 最大的特点就是采用二进制的形式传输数据,从而为后续的优化提供了更大的空间。
HTTP/2.0 中,数据以消息的形式发送,而一个消息可以被分为多个帧,每一帧的首部都有流标识,从而允许每个帧乱序发送,收到之后再进行组装。
# 多路复用
在 HTTP/1.X 中,因为队头阻塞机制,多请求并发发送需要使用多个 TCP 连接,每个 TCP 连接还要握手、慢开始,且会受到浏览器单域名并发连接上限的限制(6~8 个)。
而在 HTTP/2.0 中,所有请求都复用一个 TCP 连接,通过帧的标识就可以知道该帧属于哪一个请求,从而大大提高性能。
不过,多路复用只解决了 HTTP 的队头阻塞问题,而 TCP 队头阻塞的问题仍然存在,这是传输层层面导致的结果。
# 首部压缩
由于多个 HTTP 请求之间往往会有较多的重复头信息,HTTP/2.0 采用了首部压缩的方式(例如 HPACK 压缩格式),在服务器与客户端两边同时维护一个索引表,对于已经出现过的头信息,将其保存为 value,后续只需传输更短的 key,另一端收到后即可还原为 value。
# 服务端推送
在 HTTP/2.0,我们允许服务器在收到客户端的请求后,主动地推送其他资源。
按照原本的流程,如果客户端获取一份 HTML 文档,只有在进行预解析后才会发起新的请求去获得关联的文件;而服务端推送机制则可以将这些文件与 HTML 文档一起发送给客户端,从而减少一定的延迟。
← 传输层协议 HTTP 响应码列表 →