[笔记]《HTTP权威指南》- 实体和编码

        HTTP要确保它承载的“货物”知足如下条件:html

  • 能够被正确地识别(经过Content-Type首部说明媒体格式,Content-Language首部说明语言),以便浏览器和其余客户端能正确处理内容。
  • 能够被正确地解包(经过Content-Length首部和Content-Encoding首部)。
  • 是最新的(经过实体验证码和缓存过时控制)。
  • 符合用户的须要(基于Accept系列的内容协商首部)。
  • 在网络上能够快速有效地传输(经过范围请求、差别编码以及其余数据压缩方法)。
  • 完整到达、未被篡改(经过传输编码首部和Content-MD5校验和首部)。

1、报文是箱子,实体是货物算法

        若是把HTTP报文想象成因特网货运系统中的箱子,那么HTTP实体就是报文中实际的货物。浏览器

        HTTP实体首部描述了HTTP报文的内容。HTTP/1.1版定义了如下10个基本字体首部字段。缓存

  • Content-Type 实体中所承载对象的类型。
  • Content-Length 所传送实体主题的长度或大小。
  • Content-Language 与所传送对象最相匹配的人类语言。
  • Content-Encoding 对象数据所作的任意变换(好比,压缩)。
  • Content-Location 一个备用位置,请求时可经过它得到对象。
  • Content-Range 若是这是部分实体,这个首部说明它是总体的哪一个部分。
  • Content-MD5 实体主题内容的校验和。
  • Last-Modified 所传输内容在服务器上建立或最后修改的日期时间。
  • Expires 实体数据将要失效的日期。
  • Allow 该资源所容许的各类请求方法,例如,GET和HEAD。
  • ETag 这份文档特定实例的惟一验证码。
  • Cahce-Control 指出应该如何缓存该文档。

1 实体主体安全

        首部字段以一个空白的CRLF行结束,随后就是实体主体的原始内容。服务器

2、Content-Length:实体的大小网络

        Content-Length首部指示出报文中实体主体的字节大小。这个大小是包含了全部内容编码的,好比,对文本文件进行了gzip压缩的话,Content-Length首部就是压缩后的大小,而不是原始大小。架构

        除非使用了分块编码,不然Content-Length首部就是带有实体主体的报文必须使用的。使用Content-Length首部是为了可以检测出服务器崩溃而致使的报文截尾,并对共享持久链接的多个报文进行正确分段。并发

1 检测截尾post

        HTTP的早期版本采用关闭链接的办法来划定报文的结束。可是,没有Content-Length的话,客户端没法区分究竟是报文结束时正常的链接关闭,仍是报文传输中因为服务器崩溃而致使的链接关闭。客户端须要经过Content-Length来检测报文截尾。

        报文截尾的问题对缓存代理服务器来讲尤为严重。若是缓存服务器收到被截尾的报文却没有识别出截尾的话,它可能会存储不完整的内容并屡次使用它来提供服务。缓存代理服务器一般不会为没有显示Content-Length首部的HTTP主体作缓存,以此减小缓存已截尾报文的风险。

2 Content-Length与持久链接

        Content-Length首部对于持久链接是必不可少的。若是响应经过持久链接传送,就可能有另外一条HTTP响应紧随其后。客户端经过Content-Length首部就能够知道报文在何处结束,下一条报文从何处开始。

3 内容编码

        Content-Length首部说明的是编码后(encoded)的主体的字节长度,而不是未编码的原始主体的长度。

4 肯定实体主体长度的规则

  • 若是特定的HTTP报文类型中不容许带有主体,就忽略Content-Length首部,它是对(没有实际发送出来的)主体进行计算的。
  • 若是报文中还有描述传输编码的Transfer-Encoding首部(不采用默认的HTTP“恒等”编码),那实体就应由一个称为“零字节块”(zero-byte chunk)的特殊模式结束,除非报文已经因连接关闭而结束。
  • 若是报文中含有Content-Length首部(而且报文类型容许有实体主体),并且没有非恒等的Transfer-Encoding首部字段,那么Content-Length的值就是主体的长度。若是收到的报文中既有Content-Length首部字段又有非恒等的Transfer-Encoding首部字段,那就必须忽略Content-Length,由于传输编码会改变实体主体的表示和传输方式。
  • 若是报文使用了multipart/byterange(多部分/字节范围)媒体类型,而且没有用Content-Length首部指出实体主体的长度,那么多部分报文中的每一个部分都要说明它的大小。这种多部分类型是惟一的一种自定界的实体主体类型,所以除非发送方知道接收方能够解析它,不然就不能发送这种媒体类型。
  • 若是上面的规则都不匹配,实体就在链接关闭的时候结束。实际上,只有服务器可使用链接关闭来指示报文的结束。客户端不能用关闭链接来指示客户端报文的结束,由于这样会使服务器没法响应。

 3、实体摘要

        服务器使用Content-MD5首部发送对实体主体运行MD5算法的结果。只有产生响应的原始服务器能够计算并发送Content-MD5首部。中间代理和缓存不该当修改或添加这个首部,不然就会与验证端到端完整性的这个最终目的相冲突。Content-MD5首部是在对内容作了全部须要的内容编码以后,尚未作任何传输编码以前,计算出来的。为了验证报文的完整性,客户端必须先进行传输编码的解码,而后计算所获得的未进行传输编码的实体主体的MD5。

4、媒体类型和字符集

        Content-Type首部字段说明了实体主体的MIME类型。MIME类型是标准化的名字,用以说明做为货物运载实体的基本媒体类型。客户端应用程序使用MIME类型来解释和处理其内容。

1 文本的字符编码

Content-Type: text/html; charset=iso-8859-4

2 多部分媒体类型

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

3 多部分表格提交

        HTTP使用Content-Type:multipart/form-data或Content-Type:multipart/mixed这样的首部以及多部分主体来发送这种请求,举例以下:

Content-Type: multipart/form-data; boundary=[abcdefghijklmnopqrstuvwxyz]

        其中的boundary参数说明了分割主体中不一样部分所用的字符串。

<FORM action="http://server.com/cgi/handle"
    enctype="multipart/form-data"
    method="post">
<P>
What is your name?<INPUT type="text" name="submit-name"><BR>
What files are you sending?<INPUT type="file" name="files"><BR>
<INPUT type="submit" value="Send"><INPUT type="reset">
</FORM>

        用户代理可能会发回下面这样的数据:

Content-Type: multipart/form-data; boundary=AaB03x
--AzBo3x
Content-Dispositon: form-data; name="submit-name"
Sally
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="essayfile.txt"
Content-Type: text/plain
--BbC04y
Content-Disposition: file; filename="imagefile.gif"
Content-Type: image/gif
...contents of imagefile.gif...
--BbC04y
--AaB03x--

4 多部分范围响应

        HTTP对范围请求的响应也能够是多部分的。这样的响应中有Content-Type: mltipart/byterange首部和带有不一样范围的多部分主体。 

5、内容编码

        HTTP应用程序有时在发送以前须要对内容进行编码。

1 内容编码过程

  • 网站服务器生成原始响应报文,其中有原始的Content-Type和Content-Length首部。
  • 内容编码服务器(也多是原始的服务器或下行的代理)建立编码后的报文。编码后的报文有一样的Content-Type但Content-Length可能不一样(好比本体被压缩了)。内容编码服务器在编码后的报文中增长了Content-Encoding首部,这样接收的应用程序就能够进行解码了。
  • 接收程序获得编码后的报文,进行解码,得到原始报文。

2 内容编码类型

        HTTP定义了一些标准的内容编码类型,并容许用扩展编码的形式增添更多的编码。Content-Encoding首部就用这些标准化的代号来讲明编码时使用的算法。

3 Accept-Encoding首部

        为了不服务器使用客户端不支持的编码方式,客户端就把本身支持的内容编码方式列表放在请求的Accept-Encoding首部里发出去。若是HTTP请求中没有包含Accept-Encoding首部,服务器端就能够假设客户端可以接收任何编码方式。

6、传输编码和分块编码

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

1 可靠传输

        在HTTP中,只有少数一些状况下,所传输的报文主体可能会引起问题。其中两种状况以下所述。

        1)未知的尺寸

                若是不先生成内容,某些网关应用程序和内容编码器就没法肯定报文主体的最终大小。一般,这些服务器但愿在知道大小以前就开始传输数据。由于HTTP协议要求Content-Length首部必须在数据以前,有些服务器就是用传输编码来发送数据,并用特别的结束脚注代表数据结束。

        2)安全性

                你能够用传输编码来把报文内容扰乱,而后再共享的传输网络上发送。不过,因为像SSL这样的传输层安全体系的流行,就不多须要靠传输编码来实现安全性了。

2 Transfer-Encoding首部

        HTTP协议中只定义了下面两个首部来描述和控制传输编码。

  • Transfer-Encoding 告知接收方为了可靠地传输报文,已经对其进行了何种编码。
  • TE 用在请求首部中,告知服务器可使用那些传输编码扩展。

        下面的例子中,请求使用了TE首部来告诉服务器它能够接收分块编码(若是是HTTP/1.1应用程序的话,这就是必须的)而且愿意接受附在分块编码的报文结尾上的拖挂:

GET /new_products.html HTTP/1.1
Host: www.joes-hardware.com
User-Agent: Mozilla/4.61 [en] (WinNT; I)
TE: trailers, chunked
...

        对它的相应中包含Trasfer-Encoding首部,用于告诉接收方已经用分块编码对报文进行了传输编码:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Server: Apache/3.0
...

        在这个起始首部以后,报文的结构就将发生改变。

        传输编码的值都是大小写无关的。HTTP/1.1规定在TE首部和Transfer-Encoding首部中使用传输编码值。最新的HTTP规范只定义了一种传输编码,就是分块编码。

3 分块编码

        分块编码把报文分割为若干个大小已知的块。块之间是紧挨着发送的,这样就不须要在发送以前知道整个报文的大小。

7、验证码和新鲜度

1 新鲜度

        服务器能够用这两个首部之一来提供这种信息:Expires(过时)和Cache-Control(缓存控制)。

        Expires首部规定文档“过时”的具体时间——此后就不该当认为它仍是最新的。Expires首部的语法以下:

Expires: Sun Mar 18 23:59:59 GMT 2001

 

        客户端和服务器为了能正确使用Expires首部,它们的始终必须同步。

        Cache-Control首部能够用秒数来规定文档最长使用期——从文档离开服务器以后算起的总计时间。使用期不与时钟同步,所以能够给出更精确的结果。

2 有条件的请求与验证码

        当请求缓存服务器中的副本时,若是它再也不新鲜,缓存服务器就须要保证它有一个新鲜的副本。缓存服务器能够向原始服务器获取当前的副本。但在不少状况下,原始服务器上的文档仍然与缓存中已过时的副本相同。若是服务器上的文档和已过时的缓存副本相同,而缓存服务器仍是要从原始服务器上取文档的话,那缓存服务器就是在浪费网络带宽,给缓存服务器和原始服务器增长没必要要的负载,是全部的事情都变慢了。

        为了不这种状况,HTTP为客户端提供了一种方法,仅当资源改变时才请求副本,这种特殊请求称为有条件的请求。有条件的请求是标准的HTTP请求报文,但仅当某个特定条件为真时才执行。

GET /announce.html HTTP/1.0
If-Modified-Since: Sat, 29 Jun 2002, 14:30:00 GMT

        有条件的请求是经过以“If-”开头的有条件的首部来实现的。

        归纳一下,当客户端屡次访问同一个资源时,首先须要判断它当前的副本是否是仍然新鲜。若是再也不新鲜,它们就必须从服务器获取最新的版本。为了不在资源没有改变的状况下收到一份相同的副本,客户端能够向服务器发送有条件的请求,说明能惟一标识客户端当前副本的验证码。只在资源和客户端的副本不一样的状况下服务器才会发送其副本。

相关文章
相关标签/搜索