《图解 HTTP》读书笔记
通信模型
HTTP 协议被用于客户端和服务器之间的通信,请求访问文本或者图片等资源的一端称为客户端,而提供资源响应的一端称为服务器端。
在 HTTP 中规定,请求从客户端发出,服务器收到请求并响应后返回。HTTP 是一种无状态(stateless)协议, HTTP 协议自身不对请求和响应之间的通信状态进行保存,也就是说不对发送过的请求或者响应做持久化处理。但是随着技术发展,无状态的 HTTP 协议很难满足业务需要,比如用户登陆到一个网站之后,在这个网站的不同页面跳转的时候需要继续保持用户的登陆状态。网站为了能够掌握是哪个客户端发出的请求,需要保存用户的状态。HTTP 为了实现保持状态的功能,引入了我们熟知的 Cookie 技术来实现状态管理。
HTTP 的 GET 方法
GET 方法用来请求访问资源。如果请求的资源是文本,那么文本就保持原样返回。如果请求的资源是 CGI 程序(Common Gateway Interface,通用网关接口),那么服务端返回经过执行后的输出结果。
使用 GET 方法的请求,请求 index.html 的页面资源
使用 GET 方法的响应,返回 index.html 的页面资源
HTTP 的 POST 方法
POST 方法通常用来提交数据给服务端。虽然 GET 方法也可以用来提交数据,但一般并不使用 GET 方法。值得一提的是,GET 方法的参数会以 QueryString 的形式跟在请求链接后面而 POST 方法不会,但是不管 HTTP 的 GET 方法还是 POST 方法都是不安全的,请求数据都会被拦截。
HTTP 的报文结构
HTTP 通行过程包括从客户端发起请求和服务端响应请求的过程。用于 HTTP 协议交互的信息称为 HTTP 报文,客户端的 HTTP 报文称为请求报文,服务端的报文叫做响应报文。HTTP 报文本身是由多行数据构成的字符串文件。HTTP 报文大概可以分为 2 块,一块是报文首部,一块是报文主体,2 者之间使用空行来划分。通常情况下,报文主体不一定存在。
请求报文和响应报文的首部内容由以下数据组成。
- 请求行, 包括请求的方法,请求 URI 和 HTTP 版本
- 状态行,表示响应结果的状态码,原因短语和 HTTP 版本
- 首部字段,表示请求和响应的各种条件,属性的各类首部。一般有 4 种首付,分别是通用首部,请求首部,响应首部和实体首部
- 其他
我们使用 GET 方法请求 http://hackr.jp/index.htm 链接,请求报文和响应报文如
HTTP 提升传输效率
HTTP 在传输数据时既可以按照数据原貌直接传输,也可以在传输过程中通过编码来提升传输效率。为了让 HTTP 报文的数据容量尽可能的小,HTTP 协议规定了一个内容编码的功能用于压缩数据。举个例子,客户端请求的内容编码说明了数据的编码格式,HTTP协议按照编码格式对数据内容进行编码并传输,服务端接收数据后,HTTP 协议按照对应的编码格式对数据进行解码。常见的内容编码格式有 gzip,compress,deflate,identity。
HTTP 分块传输编码
在 HTTP 通信过程中,请求的编码实体资源未全部完成传输之前,浏览器无法显示资源。所以设计人员设计了一个功能,叫做分块传输编码 (Chunked Transfer Coding)
分块传输编码会将实体主体分成多个部分。每一块都会用十六进制来标记块的大小,而实体主体的最后一块会使用“ 0(CR+LF)”来标记。使用分块传输编码的实体主体会由接收的客户端来负责解码,恢复到编码前的实体主体。
HTTP 的 Multipart
HTTP 协议中规定,发送的一份报文主体内可以包含多种类型实体(Multipart),比如文本,视频,图片。通常在图片或者文本文件上传的时候会使用到这个功能。在 HTTP 报文中使用 Multipart 的时候需要在首部字段里面加上 Content-Type,使用 boundary 来划分不同的实体。在不同的实体的起始行前插入 “--” 标记,而在 Multipart 的最后部分插入 “--” 标记,如下图所示的 --AaB03x,--AaB03x--。
使用 Multipart/form-data 上传表单
“Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="field1"
Joe Blow
--AaB03x
Content-Disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain
...(file1.txt的数据)...
--AaB03x--”
使用 Multipart/byteranges 响应,状态码 206。该报文可以在需要响应多个范围的内容时使用。在不同的实体的起始行前插入 “--” 标记,而在 Multipart 的最后部分插入 “--” 标记,如下图所示的 --THIS_STRING_SEPARATES,--THIS_STRING_SEPARATES--。
“HTTP/1.1 206 Partial Content
Date: Fri, 13 Jul 2012 02:45:26 GMT
Last-Modified: Fri, 31 Aug 2007 02:02:20 GMT
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-Type: application/pdf
Content-Range: bytes 500-999/8000
...(范围指定的数据)...
--THIS_STRING_SEPARATES
Content-Type: application/pdf”
“Content-Range: bytes 7000-7999/8000
...(范围指定的数据)...
--THIS_STRING_SEPARATES--”
HTTP 的 范围请求 (Range Request)
HTTP 协议设计了这么一个功能,用户下载大图片过程中,若是遇到网络中断的情况,在网络恢复之后,可以从之前下载中断处恢复。这种指定范围发送的请求叫做范围请求 (Range Request),通常可以使用这个特性来做断点下载功能。
对于一份 10 000 字节大小的资源,可以使用 Range Request 只请求 5001 ~ 10 000 字节内的资源。
请求 5001 ~ 10 000 字节,使用首部字段 Range 来指定资源的范围
Range:bytes=5001-10000
从 5000 字节之后的全部范围
Range:bytes=5001-
也可以指定多重范围
Range:bytes=-3000,5000-7000
对于范围请求 (Range Request),响应会返回状态码 206 的响应报文,使用 Content-Range 来标明响应范围。值的一提的是,若是服务端无法响应范围请求,那么服务端则会返回状态码 200 OK 和 完整的实体内容。
对于多重范围的范围请求,响应报文会在首部字段 Content-Type 标明 multipart/byteranges 后返回响应报文,如下所示。
“HTTP/1.1 206 Partial Content
Date: Fri, 13 Jul 2012 02:45:26 GMT
Last-Modified: Fri, 31 Aug 2007 02:02:20 GMT
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-Type: application/pdf
Content-Range: bytes 500-999/8000
...(范围指定的数据)...
--THIS_STRING_SEPARATES
Content-Type: application/pdf”
“Content-Range: bytes 7000-7999/8000
...(范围指定的数据)...
--THIS_STRING_SEPARATES--”
HTTP 状态码
HTTP 状态码的职责是当客户端向服务器发送请求是,描述返回的请求结果。利用状态码,客户端可以知道服务端是否正常处理了请求。
- 1XX,表示接收的请求正在处理
- 2XX,请求正常处理完毕
- 3XX,需要附加操作才能完成请求,也就是重定向
- 4XX,服务器无法处理请求,也就是客户端错误
- 5XX,服务器处理请求出错,也就是服务器错误
200 OK,表示客户端发来的请求在服务端被正常处理了
204 No Content,表示客户端发来的请求在服务端被成功处理,但是响应内容中不返回实体的主体部分
206 Partial Content,表示客户端发来的范围请求被服务端处理了,响应报文中包含由 Content-Range 指定范围的实体内容
301 Moved Permanently,表示客户端请求的资源已经被永久分配了新的
URI,以后使用资源的话要用新的 URI
302 Found,表示客户端请求的资源已经被分配了新的 URI,这次临时使用这个新的 URI
303 See Other,表示客户端请求对应的资源存在着另一个 URI,应使用 GET 方法定向获取请求的资源
304 Not Modified,表示客户端请求对应的资源若是有发生变化,则响应资源,若是没有发生变化,响应时不包含任何响应的主体部分
400 Bad Request,表示客户端的请求报文中存在语法错误
401 Unauthorized,表示客户端发送的请求需要有通过 HTTP 认证的认证信息
403 Forbidden,表示客户端对资源的访问请求被拒绝了,未获得访问授权可能是发生 403 的原因
404 Not Found,表示服务端上面无法找到请求的资源,客户端的 URI 错误可能是发生 404 的原因
500 Internal Server Error,表示服务端在执行请求的时候发生了错误。
503 Service Unavailable,表示服务器处于超负载或者停机维护,现在无法处理请求。
HTTP 首部字段
HTTP 首部字段根据实际用途可以分为 4 个类型,这些首部字段只需了解常见的类型,其他类型遇到的时候可以自行搜索即可。
- 通用首部字段,请求和响应报文都会使用的首部
- 请求首部字段,从客户端向服务器发送请求时使用的首部
- 响应首部字段,从服务端向客户端返回响应报文时使用的首部
- 实体首部字段,针对请求和响应报文的实体部分使用的首部
通用首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
请求首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
If-Modified-Since | 比较资源的更新时间 |
If-None-Match | 比较实体标记(与 If-Match 相反) |
If-Range | 资源未更新时发送实体 Byte 的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
响应首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
实体首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |