目录
HTTP/1.1 请求报文
HTTP 请求报文由以下 3 个部分组成:
- 请求行(Request Start Line)
- 请求头(Request Header)
- 报文负载(Payload Data)
由于底层 TCP 协议是面向 Byte stream 的,所以 HTTP 协议需要自行设计报文边界,在开发 HTTP/1.1 Server 的 HTTP Request Parser(解析)功能时需要逐个处理。
- 请求行、请求头、请求数据这 3 部分之间通过 \r\n 隔开。
- 请求行各部分之间使用 \0 隔开。
- 请求头 Key 和 Value 之间通过 :\0 隔开。
- 多个请求头之间通过 \r\n 隔开。
请求行(Request Start Line)
请求行(Request Line)是 HTTP Request 的第一行,组成结构如下:
- Method
- \0(空格)
- URI
- \0(空格)
- Version
- \r\n(
<CR><LF>
回车换行组合)
Method 类型
- 安全性:指 Client 调用 Method,是否会导致资源状态变化。
- 幂等性:指 Client 多次调用同一个 Method,输入不变,执行的结果是否也是不变的。
Method | 功能 | 描述 | 安全性 | 幂等 |
---|---|---|---|---|
GET | SELECT | 获取一个(提供资源 ID)、或多个(提供 Filter 条件)、或全部资源。当获取多个时使用 Query Parameters 进行过滤查询。当获取多个或全部时,使用 Pagination Parameters(e.g. limit、offset、page、sortby)进行分页查询。 | √ | √ |
POST | CREATE | 根据 Request Body 创建一个资源(杜绝一次创建多个资源)。 | X | X |
PUT | UPDATE | 根据 Request Body 更新一个资源(提供完整的资源数据)。 | X | √ |
PATCH | UPDATE | 根据 Request Body 更新一个资源(提供部分的资源数据)。 | X | √ |
DELETE | DELETE | 删除一个资源。 | X | √ |
HEAD | 获取资源的元数据而非资源本身。此方法经常被用来测试超文本链接的有效性,可访问性,和最近的改变,例如:获取虚拟机镜像的属性信息。 | √ | √ | |
OPTIONS | 获取信息,例如获取服务器的性能参数,或者查询与资源相关的选项。在跨域或使用代理请求时,通常会用到。 | √ | √ |
URI 格式
其中一个完整的 URI 的组成结构如下图:
请求头(Request Header)
请求头,由由若干个 Key/Value(键值对)报头域组成,下面列出常用的请求报头域:
-
Host:传递 Hostname,用于基于 Hostname 的 HTTP Server 虚拟主机。
-
Authorization:请求身份鉴权。如果 Server 响应 401 表示未鉴权,那么 Client 可以发送一个含有 Authorization 报头域的请求,要求开始进行鉴权验证。
-
Accept:指定 Client 能接受的响应信息数据格式,e.g.
'Accept': 'application/json'
指定接受 JSON 格式数据。 -
Accept-Charset,指定 Client 能接受的响应信息字符集类型,e.g.
Accept-Charset:iso-8859-1,gb2312,utf8
。 -
Accept-Encoding:指定 Client 能接受的内容压缩类型,e.g.
Accept-Encoding:gzip.deflate
。 -
Accept-Language:指定 Client 能接受的自然语言类型,e.g.
eg:Accept-Language:zh-cn
。 -
User-Agent:将 Client 的操作系统代理、浏览器代理和其它本地属性告知 Server。
-
Cache-Control:指定请求和响应遵循的缓存机制。
-
Connection:指定 TCP 连接模式。
-
Cookie:传递 Cookie ID。
HTTP/1.1 响应报文
HTTP 响应报文由以下部分组成:
- 响应行(Response Start Line)
- 响应头(Response Header)
- 报文负载(Payload Data)
各部分之间通过 \n 换行符隔开,在开发 HTTP Server 的 HTTP Response Generator(生成)功能时,使用 “换行符“ 作为获取各个部分数据的 “边界“,使用 “空格“ 作为 Start Line 各个部分的边界。
响应行(Response Start Line)
响应行,是 HTTP Response 的第一行,组成结构如下:
- Version
- \0(空格)
- Status Code
- \0(空格)
- Status Code Description
- \r\n(
<CR><LF>
回车换行组合)
响应状态码与响应信息
-
1xx(指示信息):表示请求已接收,继续处理。
-
2xx(处理成功):表示请求已被成功接收、理解、接受。
-
3xx(处理重定向):表示要完成请求必须进行更进一步的操作。
-
4xx(客户端错误):表示请求有语法错误或请求无法实现。
-
5xx(服务器端错误):表示服务器未能实现合法的请求。
响应头(Response Header)
响应头,由若干个 Key/Value(键值对)报头域组成,下面列出常用的响应报头域:
-
Server:包含了 Server 处理请求的软件环境信息。
-
Allow:包含了 Server 支持哪些 HTTP Method。
-
Set-Cookie:包含了 Server 保存的、为 Client 分配的 Cookie。e.g.
Set-Cookie: sc=4c31523a; path=/; domain=.acookie.taobao.com
。 -
Location:包含新的 URL 地址,告知 Client 重定向到一个新的位置。
-
Content-Type:指定了 Payload Data 的格式类型。e.g.
Content-Type:text/html;charset=GB2312
。 -
Content-Length:指定了 Payload Data 的长度,以十进制数字表示。
-
Content-Encoding:指定了 Payload Data 的压缩类型,e.g.
Content-Encoding:gzip
。 -
Content-Language:描述了资源所使用的自然语言。
-
Expires:指定了响应过期的日期和时间,以此来更新缓存数据,e.g.
Expires:Thu,15 Sep 2006 16:23:12 GMT
。 -
Last-Modified:描述了资源的最后修改日期和时间。
基于 TCP Continuous ARQ 的 Pipelining 机制
HTTP/1.1 Pipelining 技术依赖 TCP Continuous ARQ(连续 ARQ)协议实现。
区别于 TCP Stop-And-Wait ARQ(停止并等待 ARQ)协议的 “串行“ ACK,TCP Continuous ARQ 使得 HTTP 在同一个 TCP 连接中,可以 “并行“ 发送多个 HTTP 请求,大大提升了传输效率。
由 TCP ACK 机制导致的队头拥塞问题
TCP 为了实现可靠传输,也引入了一个队头拥塞的问题,即:TCP 协议将 Data stream 分段为多个 Segments 按序传输,如果其中的某个 Segment 丢失了,那么这个链路上的内容都需要等待。这种由单个数据包造成的阻塞,就称为队头拥塞(Head of Line Blocking)。
反应到 HTTP 中,一个 HTTP Request 通常只会使用到一个 TCP Segment。但是一个 HTTP Response 却往往需要使用到多个 TCP Segments,这常常会导致响应队头拥塞。例如:一个 TCP 连接中传输 1 个 HTTP Responses,对应 10 个 TCP Segments。如果其中第 1、2、3 个 Responses 已被 Client 接收,但第 4 个 Response 丢失,那么后面第 5-10 个 Responses 都会被阻塞。
为了保证数据的有序性,TCP Server 就需要等第 4 个重传成功后,才能在该 Connection 中继续传输新的数据,这样就浪费了 Connection 的带宽资源。
为了解决这个问题,HTTP/1.1. 允许每个 Client 与 Server 建立 6 个 TCP 连接,以此缓和单一连接队头拥塞的问题。但每个 TCP 连接中还是会存在队头阻塞的问题。
基于 TCP Keepalive 机制实现的长连接
HTTP 的长连接与短连接,是对 TCP 协议的 2 种不同的应用模式。
- 短连接(connection mode 为 close):Server 只完成一次一次交互就会主动关闭 TCP 连接。
- 长连接(connection mode 为 keep-alive):是 HTTP/1.1 的默认模式,使用了 TCP 连接的 Keepalive 机制,该连接会存在一段时间,在该时间内 C/S 可以继续请求/响应,而无需频繁的关闭/开启。
HTTP/1.1 默认使用长连接的原因是现代网页日益复杂,Client 先发起一个 TCP 连接去抓取页面,然后 Client 分析 HTML 源码之后,发现还有很多外部资源需要抓取,那么就可以继续使用最初的 TCP 连接。从而减少了建立和关闭 TCP 连接的消耗和延迟。
Cookie 机制
HTTP 协议是一种 Stateless(无状态)传输协议,Cookie 机制就是为了让其具备 “记忆“ 能力。
Cookie 由 Server 创建,并分发给 Client 存储在浏览器中。Client 携带 Cookie 发起 Request,Server 以此来识别 Client,并加载其对应的 Context(上下文)。
Cookie 常用于广告追踪,比如:我们在访问网页视频或者图片的时候,广告商会悄悄给我们 Cookie 打上标记,方便做关联分析和行为分析,从而给我推荐一些相关内容。