详解 HTTP 协议(二)

网友投稿 614 2022-05-30

7、HTTP 报文首部之首部字段(重点分析)

(1)首部字段概述

先来回顾一下首部字段在报文的位置,HTTP 报文包含报文首部和报文主体,报文首部包含请求行 (或状态行)和首部字段。

在报文众多的字段当中,HTTP 首部字段包含的信息最为丰富。首部字段同时存在于请求和响应报文内,并涵盖 HTTP 报文相关的内容信息。使用首部字段是为了给客服端和服务器端提供报文主体大小、所使用的语言、认证信息等内容。

(2)首部字段结构

HTTP 首部字段是由首部字段名和字段值构成的,中间用冒号“:”分隔。

另外,字段值对应单个 HTTP 首部字段可以有多个值。

当 HTTP 报文首部中出现了两个或以上具有相同首部字段名的首部字段时,这种情况在规范内尚未明确,根据浏览器内部处理逻辑的不同,优先处理的顺序可能不同,结果可能并不一致。

(3)首部字段类型

首部字段根据实际用途被分为以下4种类型:

(4)通用首部字段(HTTP/1.1)

4.1 Cache-Control

通过指定首部字段 Cache-Control 的指令,就能操作缓存的工作机制。

4.1.1 可用的指令一览

可用的指令按请求和响应分类如下:

缓存请求指令:

缓存响应指令

4.1.2 表示能否缓存的指令

public 指令

Cache-Control: public

当指定使用 public 指令时,则明确表明其他用户也可利用缓存。

private 指令

Cache-Control: private

当指定 private 指令后,响应只以特定的用户作为对象,这与 public 指令的行为相反。缓存服务器会对该特定用户提供资源缓存的服务,对于其他用户发送过来的请求,代理服务器则不会返回缓存。

no-cache 指令

Cache-Control: no-cache

使用 no-cache 指令是为了防止从缓存中返回过期的资源。

客户端发送的请求中如果包含 no-cache 指令,则表示客户端将不会接收缓存过的响应。于是,“中间”的缓存服务器必须把客户端请求转发给源服务器。

如果服务器中返回的响应包含 no-cache 指令,那么缓存服务器不能对资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资源有效性进行确认,且禁止其对响应资源进行缓存操作。

Cache-Control: no-cache=Location

由服务器返回的响应中,若报文首部字段 Cache-Control 中对 no-cache 字段名具体指定参数值,那么客户端在接收到这个被指定参数值的首部字段对应的响应报文后,就不能使用缓存。换言之,无参数值的首部字段可以使用缓存。只能在响应指令中指定该参数。

no-store 指令

Cache-Control: no-store

当使用 no-store 指令时,暗示请求(和对应的响应)或响应中包含机密信息。因此,该指令规定缓存不能在本地存储请求或响应的任一部分。

注意:no-cache 指令代表不缓存过期的指令,缓存会向源服务器进行有效期确认后处理资源;no-store 指令才是真正的不进行缓存。

4.1.3 指定缓存期限和认证的指令

s-maxage 指令

Cache-Control: s-maxage=604800(单位:秒)

s-maxage 指令的功能和 max-age 指令的相同,它们的不同点是 s-maxage 指令只适用于供多位 用户使用的公共缓存服务器(一般指代理)。也就是说,对于向同一用户重复返回响应的服务器来说,这个指令没有任何作用。

另外,当使用 s-maxage 指令后,则直接忽略对 Expires 首部字段及 max-age 指令的处理。

max-age 指令

Cache-Control: max-age=604800(单位:秒)

当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓存时间数值比指定的时间更小,那么客户端就接收缓存的资源。另外,当指定 max-age 的值为0,那么缓存服务器通常需要将请求转发给源服务器。

当服务器返回的响应中包含 max-age 指令时,缓存服务器将不对资源的有效性再作确认,而 max-age 数值代表资源保存为缓存的最长时间。

应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情况时,会优先处理 max-age 指令,并忽略掉 Expires 首部字段;而 HTTP/1.0 版本的缓存服务器则相反。

min-fresh 指令

Cache-Control: min-fresh=60(单位:秒)

min-fresh 指令要求缓存服务器返回至少还未过指定时间的缓存资源。

max-stale 指令

Cache-Control: max-stale=3600(单位:秒)

使用 max-stale 可指示缓存资源,即使过期也照常接收。

如果指令未指定参数值,那么无论经过多久,客户端都会接收响应;如果指定了具体参数值,那么即使过期,只要仍处于 ma x-stale 指定的时间内,仍旧会被客户端接收。

only-if-cached 指令

Cache-Control: only-if-cached

表示客户端仅在缓存服务器本地缓存目标资源的情况下才会要求其返回。换言之,该指令要求缓存服务器不重新加载响应,也不会再次确认资源的有效性。

must-revalidate 指令

Cache-Control: must-revalidate

使用 must-revalidate 指令,代理会向源服务器再次验证即将返回的响应缓存目前是否仍有效。另外,使用 must-revalidate 指令会忽略请求的 max-stale 指令。

proxy-revalidate 指令

Cache-Control: proxy-revalidate

proxy-revalidate 指令要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性。

no-transform 指令

Cache-Control: no-transform

使用 no-transform 指令规定无论是在请求还是响应中,缓存都不能改变实体主体的媒体类型。这样做可防止缓存或代理压缩图片等类似操作。

4.1.4 Cache-Control 扩展

Cache-Control: private, community="UCI"

通过 cache-extension 标记(token),可以扩展 Cache-Control 首部字段内的指令。上述 community 指令即扩展的指令,如果缓存服务器不能理解这个新指令,就会直接忽略掉。

4.2 Connection

Connection 首部字段具备以下两个作用:

控制不再转发的首部字段

Connection: Upgrade

在客户端发送请求和服务器返回响应中,使用 Connection 首部字段,可控制不再转发给代理的首部字段,即删除后再转发(即Hop-by-hop首部)。

管理持久连接

Connection: close

HTTP/1.1 版本的默认连接都是持久连接。当服务器端想明确断开连接时,则指定 Connection 首部字段的值为 close。

Connection: Keep-Alive

HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接。为此,如果想在旧版本的 HTTP 协议上维持持续连接,则需要指定 Connection 首部字段的值为 Keep-Alive。

4.3 Date

表明创建 HTTP 报文的日期和时间。

Date: Mon, 10 Jul 2017 15:50:06 GMT

HTTP/1.1 协议使用在 RFC1123 中规定的日期时间的格式。

4.4 Pragma

Pragma 首部字段是 HTTP/1.1 版本之前的历史遗留字段,仅作为与 HTTP/1.0 的向后兼容而定义。

Pragma: no-cache

该首部字段属于通用首部字段,但只用在客户端发送的请求中,要求所有的中间服务器不返回缓存的资源。

所有的中间服务器如果都能以 HTTP/1.1 为基准,那直接采用 Cache-Control: no-cache 指定缓存的处理方式最为理想。但是要整体掌握所有中间服务器使用的 HTTP 协议版本却是不现实的,所以,发送的请求会同时包含下面两个首部字段:

Cache-Cont rol: no-cache

Pragma: no-cache

4.5 Trailer

Trailer: Expires

首部字段 Trailer 会事先说明在报文主体后记录了哪些首部字段。可应用在 HTTP/1.1 版本分块传输编码时。

4.6 Transfer-Encoding

Transfer-Encoding: chunked

规定了传输报文主体时采用的编码方式。

HTTP/1.1 的传输编码方式仅对分块传输编码有效。

4.7 Upgrade

Upgrade: TSL/1.0

用于检测 HTTP 协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。

4.8 Via

Via: 1.1 a1.sample.com(Squid/2.7)

为了追踪客户端和服务器端之间的请求和响应报文的传输路径。

报文经过代理或网关时,会现在首部字段 Via 中附加该服务器的信息,然后再进行转发。

首部字段 Via 不仅用于追踪报文的转发,还可避免请求回环的发生。

4.9 Warning

该首部字段通常会告知用户一些与缓存相关的问题的警告。

Warning 首部字段的格式如下:

Warning:[警告码][警告的主机:端口号] "[警告内容]"([日期时间])

最后的日期时间可省略。

HTTP/1.1 中定义了7种警告,警告码对应的警告内容仅推荐参考,另外,警告码具备扩展性,今后有可能追加新的警告码。

(5)请求首部字段(HTTP/1.1)

6.1 Accept-Ranges

Accept-Ranges: bytes

首部字段 Accept-Ranges 是用来告知客户端服务器是否能处理范围请求,以指定获取服务器端某个部分的资源。

可指定的字段值有两种,可处理范围请求时指定其为 bytes,反之则指定其为 none。

6.2 Age

Age: 1200

首部字段 Age 能告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。

若创建该响应的服务器是缓存服务器,Age 值是指缓存后的响应再次发起认证到认证完成的时间值。代理创建响应时必须加上首部字段 Age。

6.3 ETag

ETag: "usagi-1234"

首部字段 ETag 能告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。

另外,当资源更新时,ETag 值也需要更新。生成 ETag 值时,并没有统一的算法规则,而仅仅是由服务器来分配。

ETag 中有强 ETag 值和弱 ETag 值之分。强 ETag 值,不论实体发生多么细微的变化都会改变其值;弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/: ETag: W/"usagi-1234"。

6.4 Location

Location: http://www.sample.com/sample.html

使用首部字段 Location 可以将响应接收方引导至某个与请求 URI 位置不同的资源。

基本上,该字段会配合 3xx :Redirection 的响应,提供重定向的 URI。

几乎所有的浏览器在接收到包含首部字段 Location 的响应后,都会强制性地尝试对已提示的重定向资源的访问。

6.5 Proxy-Authenticate

Proxy-Authenticate: Basic realm="Usagidesign Auth"

首部字段 Proxy-Authenticate 会把由代理服务器所要求的认证信息发送给客户端。

它与客户端和服务器之间的 HTTP 访问认证的行为相似,不同之处在于其认证行为是在客户端与代理之间进行的。

6.6 Retry-After

Retry-After: 180

首部字段 Retry-After 告知客户端应该在多久之后再次发送请求。主要配合状态码 503 Service Unavailable 响应,或 3xx Redirect 响应一起使用。

字段值可以指定为具体的日期时间(Mon, 10 Jul 2017 15:50:06 GMT 等格式),也可以是创建响应后的秒数。

6.7 Server

Server: Apache/2.2.6 (Unix) PHP/5.2.5

首部字段 Server 告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息。不单单会标出服务器上的软件应用名称,还有可能包括版本号和安装时启用的可选项。

6.8 Vary

Vary: Accept-Language

首部字段 Vary 可对缓存进行控制。源服务器会向代理服务器传达关于本地缓存使用方法的命令。

从代理服务器接收到源服务器返回包含 Vary 指定项的响应之后,若再要进行缓存,仅对请求中含有相同 Vary 指定首部字段的请求返回缓存。即使对相同资源发起请求,但由于 Vary 指定的首部字段不相同,因此必须要从源服务器重新获取资源。

6.9 WWW-Authenticate

WWW-Authenticate: Basic realm="Usagidesign Auth"

首部字段 WWW-Authenticate 用于 HTTP 访问认证。它会告知客户端适用于访问请求 URI 所指定资源的认证方案(Basic 或是 Digest)和带参数提示的质询(challenge)。

(7) 实体首部字段(HTTP/1.1)

7.1 Allow

Allow: GET, HEAD

详解 HTTP 协议(二)

首部字段 Allow 用于通知客户端能够支持 Request-URI 指定资源的所有 HTTP 方法。

当服务器接收到不支持的 HTTP 方法时,会以状态码 405 Method Not Allowed 作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 Allow 后返回。

7.2 Content-Encoding

Content-Encoding: gzip

首部字段 Content-Encoding 会告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩。

主要采用这 4 种内容编码的方式(gzip、compress、deflate、identity)。

7.3 Content-Language

Content-Language: zh-CN

首部字段 Content-Language 会告知客户端,实体主体使用的自然语言(指中文或英文等语言)。

7.4 Content-Length

Content-Length: 15000

首部字段 Content-Length 表明了实体主体部分的大小(单位是字节)。对实体主体进行内容编码传输时,不能再使用 Content-Length首部字段。

7.5 Content-Location

Content-Location: http://www.sample.com/index.html

首部字段 Content-Location 给出与报文主体部分相对应的 URI。和首部字段 Location 不同,Content-Location 表示的是报文主体返回资源对应的 URI。

7.6 Content-MD5

Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==

首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。

7.7 Content-Range

Content-Range: bytes 5001-10000/10000

针对范围请求,返回响应时使用的首部字段 Content-Range,能告知客户端作为响应返回的实体的哪个部分符合范围请求。字段值以字节为单位,表示当前发送部分及整个实体大小。

7.8 Content-Type

Content-Type: text/html; charset=UTF-8

首部字段 Content-Type 说明了实体主体内对象的媒体类型。和首部字段 Accept 一样,字段值用 type/subtype 形式赋值。参数 charset 使用 iso-8859-1 或 euc-jp 等字符集进行赋值。

7.9 Expires

Expires: Mon, 10 Jul 2017 15:50:06 GMT

首部字段 Expires 会将资源失效的日期告知客户端。

缓存服务器在接收到含有首部字段 Expires 的响应后,会以缓存来应答请求,在 Expires 字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会 转向源服务器请求资源。

源服务器不希望缓存服务器对资源缓存时,最好在 Expires 字段内写入与首部字段 Date 相同的时间值。

7.10 Last-Modified

Last-Modified: Mon, 10 Jul 2017 15:50:06 GMT

首部字段 Last-Modified 指明资源最终修改的时间。一般来说,这个值就是 Request-URI 指定资源被修改的时间。但类似使用 CGI 脚本进行动态数据处理时,该值有可能会变成数据最终修改时的时间。

(8)为 Cookie 服务的首部字段

8.1 Set-Cookie

Set-Cookie: status=enable; expires=Mon, 10 Jul 2017 15:50:06 GMT; path=/;

下面的表格列举了 Set-Cookie 的字段值 。

8.1.1 expires 属性

Cookie 的 expires 属性指定浏览器可发送 Cookie 的有效期。

当省略 expires 属性时,其有效期仅限于维持浏览器会话(Session)时间段内。这通常限于浏览器应用程序被关闭之前。

另外,一旦 Cookie 从服务器端发送至客户端,服务器端就不存在可以显式删除 Cookie 的方法。但可通过覆盖已过期的 Cookie,实现对客户端 Cookie 的实质性删除操作。

8.1.2 path 属性

Cookie 的 path 属性可用于限制指定 Cookie 的发送范围的文件目录。

8.1.3 domain 属性

通过 Cookie 的 domain 属性指定的域名可做到与结尾匹配一致。比如,当指定 example.com 后,除example.com 以外,www.example.com 或 www2.example.com 等都可以发送 Cookie。

因此,除了针对具体指定的多个域名发送 Cookie 之 外,不指定 domain 属性显得更安全。

8.1.4 secure 属性

Cookie 的 secure 属性用于限制 Web 页面仅在 HTTPS 安全连接时,才可以发送 Cookie。

8.1.5 HttpOnly 属性

Cookie 的 HttpOnly 属性是 Cookie 的扩展功能,它使 JavaScript 脚本无法获得 Cookie。其主要目的为防止跨站脚本攻击(Cross-site scripting,XSS)对 Cookie 的信息窃取。

通过上述设置,通常从 Web 页面内还可以对 Cookie 进行读取操作。但使用 JavaScript 的 document.cookie 就无法读取附加 HttpOnly 属性后的 Cookie 的内容了。因此,也就无法在 XSS 中利用 JavaScript 劫持 Cookie 了。

8.2 Cookie

Cookie: status=enable

首部字段 Cookie 会告知服务器,当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie。接收到多个 Cookie 时,同样可以以多个 Cookie 形式发送。

(9)其他首部字段

HTTP 首部字段是可以自行扩展的。所以在 Web 服务器和浏览器的应用上,会出现各种非标准的首部字段。

以下是最为常用的首部字段。

9.1 X-Frame-Options

X-Frame-Options: DENY

首部字段 X-Frame-Options 属于 HTTP 响应首部,用于控制网站内容在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是为了防止点击劫持(clickjacking)攻击。首部字段 X-Frame-Options 有以下两个可指定的字段值:

DENY:拒绝

SAMEORIGIN:仅同源域名下的页面(Top-level-browsing-context)匹配时许可。(比如,当指定 http://sample.com/sample.html 页面为 SAMEORIGIN 时,那么 sample.com 上所有页面的 frame 都被允许可加载该页面,而 example.com 等其他域名的页面就不行了)

9.2 X-XSS-Protection

X-XSS-Protection: 1

首部字段 X-XSS-Protection 属于 HTTP 响应首部,它是针对跨站脚本攻击(XSS)的一种对策,用于控制浏览器 XSS 防护机制的开关。首部字段 X-XSS-Protection 可指定的字段值如下:

0 :将 XSS 过滤设置成无效状态

1 :将 XSS 过滤设置成有效状态

9.3 DNT

DNT: 1

首部字段 DNT 属于 HTTP 请求首部,其中 DNT 是 Do Not Track 的简称,意为拒绝个人信息被收集,是表示拒绝被精准广告追踪的一种方法。首部字段 DNT 可指定的字段值如下:

0 :同意被追踪

1 :拒绝被追踪

由于首部字段 DNT 的功能具备有效性,所以 Web 服务器需要对 DNT做对应的支持。

9.4 P3P

P3P: CP="CAO DSP LAW CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa OUR BUS IND

首部字段 P3P 属于 HTTP 响应首部,通过利用 P3P(The Platform for Privacy Preferences,在线隐私偏好平台)技术,可以让 Web 网站上的个人隐私变成一种仅供程序可理解的形式,以达到保护用户隐私的目的。

要进行 P3P 的设定,需按以下操作步骤进行:

步骤 1:创建 P3P 隐私

步骤 2:创建 P3P 隐私对照文件后,保存命名在 /w3c/p3p.xml

步骤 3:从 P3P 隐私中新建 Compact policies 后,输出到 HTTP 响应中

8、HTTP 响应状态码(重点分析)

(1)状态码概述

HTTP 状态码负责表示客户端 HTTP 请求的返回结果、标记服务器端的处理是否正常、通知出现的错误等工作。

HTTP 状态码如 200 OK ,以 3 位数字和原因短语组成。数字中的第一位指定了响应类别,后两位无分类。

不少返回的响应状态码都是错误的,但是用户可能察觉不到这点。比如 Web 应用程序内部发生错误,状态码依然返回 200 OK。

(2)状态码类别

我们可以自行改变 RFC2616 中定义的状态码或者服务器端自行创建状态码,只要遵守状态码的类别定义就可以了。

(3)常用状态码解析

HTTP 状态码种类繁多,数量达几十种。其中最常用的有以下 14 种,一起来看看。

3.1 200 OK

表示从客户端发来的请求在服务器端被正常处理了。

3.2 204 No Content

代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的主体。

一般在只需要从客户端向服务器端发送消息,而服务器端不需要向客户端发送新消息内容的情况下使用。

3.3 206 Partial Content

表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 首部字段指定范围的实体内容。

3.4 301 Moved Permanently

永久性重定向。表示请求的资源已被分配了新的 URI。以后应使用资源现在所指的 URI。也就是说,如果已经把资源对应的 URI 保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存。

3.5 302 Found

临时性重定向。表示请求的资源已被分配了新的 URI,希望用户(本次)能使用新的 URI 访问。

和 301 Moved Permanently 状态码相似,但 302 Found 状态码代表资源不是被永久移动,只是临时性质的。换句话说,已移动的资源对应的 URI 将来还有可能发生改变。

3.6 303 See Other

表示由于请求的资源存在着另一个 URI,应使用 GET 方法定向获取请求的资源。

303 See Other 和 302 Found 状态码有着相同的功能,但 303 See Other 状态码明确表示客户端应采用 GET 方法获取资源,这点与 302 Found 状态码有区别。

3.7 304 Not Modified

表示客户端发送附带条件的请求时,服务器端允许请求访问的资源,但未满足条件的情况。

304 Not Modified 状态码返回时,不包含任何响应的主体部分。

304 Not Modified 虽然被划分到 3xx 类别中,但和重定向没有关系。

3.8 307 Temporary Redirect

临时重定向。该状态码与 302 Found 有着相同的含义。

3.9 400 Bad Request

表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。

另外,浏览器会像 200 OK 一样对待该状态码。

3.10 401 Unauthorized

表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。

另外,若之前已进行过 1 次请求,则表示用户认证失败。

返回含有 401 Unauthorized 的响应必须包含一个适用于被请求资源的 WWW-Authenticate 首部用以质询(challenge)用户信息。

3.11 403 Forbidden

表明对请求资源的访问被服务器拒绝了。服务器端没有必要给出详细的拒绝理由,当然也可以在响应报文的实体主体部分对原因进行描述。

3.12 404 Not Found

表明服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由的时候使用。

3.13 500 Internal Server Error

表明服务器端在执行请求时发生了错误。也可能是 Web 应用存在的 bug 或某些临时的故障。

3.14 503 Service Unavailable

表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。如果事先得知解除以上状况需要的时间,最好写入 Retry-After 首部字段再返回给客户端。

9、HTTP 报文实体

(1)HTTP 报文实体概述

大家请仔细看看上面示例中,各个组成部分对应的内容。

接着,我们来看看报文和实体的概念。如果把 HTTP 报文想象成因特网货运系统中的箱子,那么 HTTP 实体就是报文中实际的货物。

报文:是网络中交换和传输的数据单元,即站点一次性要发送的数据块。报文包含了将要发送的完整的数据信息,其长短很不一致,长度不限且可变。

实体:作为请求或响应的有效载荷数据(补充项)被传输,其内容由实体首部和实体主体组成。(实体首部相关内容在上面第六点中已有阐述。)

我们可以看到,上面示例右图中深红色框的内容就是报文的实体部分,而蓝色框的两部分内容分别就是实体首部和实体主体。而左图中粉红框内容就是报文主体。

通常,报文主体等于实体主体。只有当传输中进行编码操作时,实体主体的内容发生变化,才导致它 和报文主体产生差异。

(2)内容编码

HTTP 应用程序有时在发送之前需要对内容进行编码。例如,在把很大的 HTML 文档发送给通过慢速连接上来的客户端之前,服务器可能会对其进行压缩,这样有助于减少传输实体的时间。服务器还可以把内容搅乱或加密,以此来防止未授权的第三方看到文档的内容。

这种类型的编码是在发送方应用到内容之上的。当内容经过内容编码后,编好码的数据就放在实体主体中,像往常一样发送给接收方。

内容编码类型:

(3)传输编码

内容编码是对报文的主体进行的可逆变换,是和内容的具体格式细节紧密相关的。

传输编码也是作用在实体主体上的可逆变换,但使用它们是由于架构方面的原因,同内容的格式无关。使用传输编码是为了改变报文中的数据在网络上传输的方式。

(4)分块编码

分块编码把报文分割成若干已知大小的块。块之间是紧挨着发送的,这样就不需要在发送之前知道整个报文的大小了。分块编码是一种传输编码,是报文的属性。

分块编码与持久连接

若客户端与服务器端之间不是持久连接,客户端就不需要知道它在读取的主体的长度,而只需要读取到服务器关闭主体连接为止。

当使用持久连接时,在服务器写主体之前,必须知道它的大小并在 Content-Length 首部中发送。如果服务器动态创建内容,就可能在发送之前无法知道主体的长度。

分块编码为这种困难提供了解决方案,只要允许服务器把主体分块发送,说明每块的大小就可以了。因为主体是动态创建的,服务器可以缓冲它的一部分,发送其大小和相应的块,然后在主体发送完之前重复这个过程。服务器可以用大小为 0 的块作为主体结束的信号,这样就可以继续保持连接,为下一个响应做准备。

来看看一个分块编码的报文示例:

(5)多部分媒体类型

MIME 中的 multipart(多部分)电子邮件报文中包含多个报文,它们合在一起作为单一的复杂报文发送。每一部分都是独立的,有各自的描述其内容的集,不同部分之间用分界字符串连接在一起。

相应得,HTTP 协议中也采纳了多部分对象集合,发送的一份报文主体内可包含多种类型实体。

多部分对象集合包含的对象如下:

multipart/form-data:在 Web 表单文件上传时使用。

multipart/byteranges:状态码 206 Partial Content 响应报文包含了多个范围的内容时使用。

(6)范围请求

假设你正在下载一个很大的文件,已经下了四分之三,忽然网络中断了,那下载就必须重头再来一遍。为了解决这个问题,需要一种可恢复的机制,即能从之前下载中断处恢复下载。要实现该功能,这就要用到范围请求。

有了范围请求, HTTP 客户端可以通过请求曾获取失败的实体的一个范围(或者说一部分),来恢 复下载该实体。当然这有一个前提,那就是从客户端上一次请求该实体到这一次发出范围请求的时间段内,该对象没有改变过。例如:

10、与 HTTP 协作的 Web 服务器

HTTP 通信时,除客户端和服务器外,还有一些用于协助通信的应用程序。如下列出比较重要的几个:代理、缓存、网关、隧道、Agent 代理。

(1)代理

出于安全考虑,通常会将代理作为转发所有 Web 流量的可信任中间节点使用。代理还可以对请求和响应进行过滤,安全上网或绿色上网。

(2)缓存

浏览器第一次请求:

浏览器再次请求:

Web 缓存或代理缓存是一种特殊的 HTTP 代理服务器,可以将经过代理传输的常用文档复制保存起来。

下一个请求同一文档的客户端就可以享受缓存的私有副本所提供的服务了。客户端从附近的缓存下载文档会比从远程 Web 服务器下载快得多。

(3)网关

网关是一种特殊的服务器,作为其他服务器的中间实体使用。通常用于将 HTTP 流量转换成其他的协议。网关接收请求时就好像自己是资源的源服务器一样。客户端可能并不知道自己正在跟一个网关进行通信。

(4)隧道

隧道是会在建立起来之后,就会在两条连接之间对原始数据进行盲转发的 HTTP 应用程序。HTTP 隧道通常用来在一条或多条 HTTP 连接上转发非 HTTP 数据,转发时不会窥探数据。

HTTP 隧道的一种常见用途就是通过 HTTP 连接承载加密的安全套接字层(SSL)流量,这样 SSL 流量就可以穿过只允许 Web 流量通过的防火墙了。

(5) Agent 代理

Agent 代理是代表用户发起 HTTP 请求的客户端应用程序。所有发布 Web 请求的应用程序都是 HTTP Agent 代理。

HTTP TCP/IP 单片机

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:深度神经网络发展历程全回顾:如何加速 DNN 运算?
下一篇:Python 3.9:很酷的新功能供您试用
相关文章