part of Hypertext Transfer Protocol -- HTTP/1.1

RFC 2616 Fielding, et al.

14 头字段规定

  该章节定义了HTTP1.1标准所包含的所有头字段的相关语法和含义。实体头字段是接收者或者发送者所涉及到的,并不区分是客户端还是服务器所拥有,而是依据是谁发送或者是谁接受该实体的字段。

14.1 Accept

  Accept请求头字段可以用来指定一个能被响应接受的确定的媒体类型。Accept头字段可以用来标识那些在请求中特别指定类型的一个小范围的集合,比如请求内联图片的情况。

         Accept         =  "Accept" ":" #( media-range(媒体范围) [ accept-params (可接受的参数)] )

         media-range    = ( "*/*"  | ( type "/" "*" )   | ( type "/" subtype )   ) *( ";" parameter )

         accept-params  = ";" "q" "=" qvalue *( accept-extension(可接受的扩展) )

         accept-extension = ";" token(记号) [ "=" ( token | quoted-string(引用字符串) ) ]

  星号"*"字符用来把媒体类型归类到ranges中,"*/*" 表示所有媒体类型都可以接受,"type/*"标明该媒体类型下的所有子类型。media-range可以包含适当范围内的媒体类型参数。

  每个media-range都可以跟随一个或多个accept-params参数,以q参数开始,用来表明相对的权重因子。第一个q参数(如果有的话)将media-range参数从accept-params字段中分隔开。权重参数允许用户或用户代理指示对该媒体范围的相对偏好程度,q的值在0到1范围内。默认的值是1。

  请注意:使用“q”参数名称将媒体类型参数从Accept扩展参数中分离出来是有历史实践性的。尽管这可能会从媒体范围中阻止任何叫做“q”的媒体类型,但是由于IANA(因特网编号管理局)注册表中缺少"q"字段的相关记录,并且Accept中很少使用任何媒体类型的参数,因此这种事情不太可能发生。

  一个简单的例子:

         Accept: audio/*; q=0.2, audio/basic

  可以理解为我第一优先需要“audio/basic”格式,但是在降低百分之八十的标准后给我传送其他的audio类型也是可以的。

  如果没有Accept投资段,那么假设客户端可以接受任何的媒体类型。如果存在Accept头字段,但是服务器无法发送一个包含Accept字段中可接受的响应,那么就会返回一个406状态码。

  一个稍微复杂点的例子:

         Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c

  口头上的解释是,首选的媒体类型是text/html和text/x-c,但是如果他们不存在,那么可以返回text/x-dvi实体,但是如果也不存在,那么就需要发送那个text/plain实体。

  媒体范围(Media ranges)可以被更特定的媒体范围(Media ranges)或特定的媒体类型(media types)覆盖。如果一个给定类型应用了多个媒体范围,那么最特定的会被采用。我们来看下面的例子:

         Accept: text/*, text/html, text/html;level=1, */*

  拥有以下的优先级

         1) text/html;level=1

         2) text/html

         3) text/*

         4) */*

  与给定类型关联的媒体类型权重因子是通过找到与该类型匹配的具有最高优先级的媒体范围来确定的。例如,

 Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5

  将会导致其关联的权重值是下面这样:

         text/html;level=1    = 1

         text/html                 = 0.7

         text/plain                = 0.3

         image/jpeg             = 0.5

         text/html;level=2     = 0.4

         text/html;level=3     = 0.7

  注意:用户代理可能会为某些媒体范围提供一组默认的权重值。但是,除非用户代理是一个封闭的系统,不能与其他执行中的代理(rendering agents)交互,否则这个默认设置应该由用户配置。

14.2 Accept-Charset

  Accept-Charset 请求头字段可以用来标示怎样的字符集可以在响应中使用。该字段允许客户端有能力去理解综合性更强或者具有特殊用途的字符集,具有向能够在这些字符集中表示文档的服务器发出信号的能力。

        Accept-Charset = "Accept-Charset" ":" 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )

  在3.4小节我们解释了有关于字符集的值的相关信息。每一个字符可以拥有一个用来表示该字符权重的相关的值。权重的默认值是1。下面我们看一个例子:

        Accept-Charset: iso-8859-5, unicode-1-1;q=0.8

  如果存在特殊的星号“*”在Accept-Charset字段中,匹配在Accept-Charset字段中没有提及的其他所有的字符集(包括ISO-8859-1)。如果该头字段中不存在星号,没有明确提及的所有字符集都获得权重值0,除了ISO-8859-1,如果没有明确提及,则获得权重值1。

  如果没有Accept-Charset头字段,则说明任何字符都是可以接受的。如果存在该字段,但是服务器并没有在响应中传递该字段允许的字符集,那么服务器需要返回一个406状态码,尽管传送一个不符合的响应也是被允许的。

14.3 Accept-Encoding

  Accept-Encoding请求头字段与Accept头字段类似,但是限制了在响应用允许使用的内容编码(content-codeings,第3.5小节)。

         Accept-Encoding  = "Accept-Encoding" ":"

                            1#( codings [ ";" "q" "=" qvalue ] )

         codings        = ( content-coding | "*" )

  使用该字段的例子:

         Accept-Encoding: compress, gzip

         Accept-Encoding:

         Accept-Encoding: *

         Accept-Encoding: compress;q=0.5, gzip;q=1.0

         Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0

  服务器根据Accept-Encoding字段测试内容编码(content-coding)是否可以接受,规则如下:

  1.内容编码(content-coding)是否是在Accept-Encoding字段中列出的,如果是则可以接受,除非它伴有的权重值是0.(就像3.9小节所描述的,权重值为0则认为无法接受)

  2.如果Accept-Encoding字段中存在特殊的星号“*”,那么意味着在任何在该字段中未明确说明的内容编码都是可以接受的。

  3.如果有多个被允许的内容编码,那么权重值最高的优先。

  4.身份(identity)内容编码总是可以被接受的,除非在Accept-Encoding字段中的identity字段的权重值是0,或者在字段中包含了“*;q=0”并且没有明确的“identity”内容编码。如果不存在Accept-Encoding,那么只有“identity”是被允许的。

  如果一个请求中存在Accept-Encoding字段,但是服务器无法提供该字段范围内的响应,那么服务器需要返回一个406错误响应。

  如果请求中没有Accept-Encoding头字段,那么服务器则假设客户端可以接受任何类型编码的内容。在这种情况下,如果“identity”是被允许的内容编码之一,那么服务器需要使用“identity”内容编码,除非有额外的信息表明其他的内容编码对客户端更有意义。

  注意:如果请求不包含Accept-Encoding字段,如果"identity"内容编码不可用,那么HTTP/1.0客户端会使用通用的content-codings(即,“gzip”和“compress”);一些较老的客户端可能会不正确地显示与其他内容编码一起发送的消息。服务器还可以根据特定用户代理或客户端的信息做出此决定。

  注意:大多数HTTP/1.0应用程序不识别或不遵守与内容编码相关的qvalue。这意味着qvalues将不能工作,x-gzip或x-compress中不允许使用qvalues。

14.4 Accept-Language

  该字段也Tm跟Accept字段类似,但是它限制了请求中需要的自然语言集合的首选范围。语言标识符在3.10小节中已经详细说明。

         Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q" "=" qvalue ] )

         language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )

  每一个语言范围(language-range)可以拥有一个表示预计用户在该语言范围内更倾向的语言的相关联的权重值。默认的权重值是1。比如:

         Accept-Language: da, en-gb;q=0.8, en;q=0.7

  意味着:“我需要丹麦语(Danish),但是英式英语或者其他类型的英语也是可以接受的”。如果语言范围正好等于标记,或者正好等于标记的前缀,则语言范围匹配语言标记,使得前缀后面的第一个标记字符是“-”。如果在Accept-Language字段中存在特殊范围“*”,则与Accept-Language字段中存在的任何其他范围不匹配的每个标记匹配。

  注意:前缀匹配规则的这种使用并不意味着语言标签是以这样的方式分配给语言的,即如果用户理解具有特定标记的语言,那么该用户也将理解具有该标记为前缀的所有标记的语言。如果是这样的话,前缀规则只允许使用前缀标签。

   Accept-Language字段分配给语言标签的权重因子是与语言标签匹配的字段中最长的语言范围的权重值。如果字段中没有语言范围与标签匹配,则分配的语言权重值为0。如果请求中不存在Accept-Language字段头,则服务器应假定所有语言都同样可接受。如果存在Accept-Language字段头,则分配大于0的权重值的所有语言都是可接受的。

  在每次请求中发送带有用户完整语言首选项的Accept-Language报头可能与用户的隐私期望相反。有关这个问题的讨论,请参阅第15.1.4节。

  由于可理解性高度依赖于单个用户,因此建议客户端应用程序允许用户可以选择语言首选项。如果选择不可用,则不能在请求中给出 Accept-Language头字段。

  注意:当用户能够选择语言偏好时,我们希望提醒开发者,用户并不熟悉上述语言匹配的细节,并且应该提供适当的指导。举个例子,用户可能会假设在选择“en-gb”时,如果英式英语不可用,他们会得到任何类型的英语文档。在这种情况下,用户代理可能会建议使用“EN”以获得最佳匹配行为。

14.5 Accept-Ranges

  Accept-Ranges响应头字段允许服务器表明其所接受资源的范围:

          Accept-Ranges     = "Accept-Ranges" ":" acceptable-ranges

          acceptable-ranges = 1#range-unit | "none"

  接受字节范围(byte-range)请求的源服务器可以发送

          Accept-Ranges: bytes

  但是我们并不需要这样做。客户端可以生成字节范围(byte-range)请求,而不为所涉及的资源接收此报头。范围单元(Range units)在3.12小节中做了说明。

  如果发送了如下的字段,那么服务器不会接受任何范围的请求。

          Accept-Ranges: none

  建议客户端不要尝试范围请求。

14.6 Age

  Age响应头字段传递发送方对该响应(或重新验证)在原始服务器上生成以来的时间的大致估计,如果缓存的响应的生命周期不超过新鲜度(fresh),那么它就是最新的。在13.2.3小节中指定了如何去计算Age的值。

           Age = "Age" ":" age-value

           age-value = delta-seconds

  Age的值是非负的十进制整数,表示时间(以秒为单位)。如果一个缓存接收到一个大于它所能表示的最大正整数的值,或者Age计算出的值溢出,那么它必须发送一个值为2147483648(2^31)的Age头字段。包含缓存的HTTP/1.1服务器必须在其自身缓存生成的每个响应中包含Age头字段。缓存应该使用至少31位的算术类型。

14.7 Allow

  Allow实体头字段列出了由请求URI(Request-URI)所标识的资源所支持的一组方法。此字段的目的是严格的告知接收方与该资源关联的有效方法。Allow字段必须在405(Method Not Allowed)响应中存在。

          Allow   = "Allow" ":" #Method

  使用例子:

          Allow: GET, HEAD, PUT

  该字段无法阻止客户端尝试其他方法。

  但是,我们应该遵循Allow头字段的值所给出的指示。被允许使用的方法的实际集合会在每一次请求的元服务器中明确的指定。

   Allow头字段可以提供一个PUT方法以使用户提前知道一个新资源或者一个被修改的资源当前所支持的方法。服务器无需支持这些方法,但是需要在响应中包含一个Allow头字段告知用户该资源实际支持的方法有哪些。

  一个代理不能修改Allow头字段中的内容既是它完全无法理解所有方法所具有的特性,因为可能我们的客户端在与服务器交流的时候有其他的用意。

14.8 Authorization

  用户代理希望通过服务器(通常是在收到401响应之后,但不一定是在收到401响应之后)进行身份验证,验证的方法是在请求中包含一个Authorization请求头字段。Authorization字段值由凭证(credentials)组成,凭证包含所请求资源范围的用户代理的身份验证信息。

         Authorization  = "Authorization" ":" credentials

   该("HTTP Authentication:Basic and Digest Access Authentication")文章介绍了HTTP如何访问身份验证信息。如果某个请求通过了身份验证并指定了一个域,那么该域内的所有其他请求应该具有相同的凭证(假设身份验证方案本身不需要其他凭证,例如根据质询值变化的凭证或使用同步时钟)。

  当共享缓存(参见第13.7节)接收到包含Authorization字段的请求时,它不能返回相应的响应作为对任何其他请求的回复,除非存在以下特定情况之一:

  1.如果一个响应包含了“s-maxage”缓存控制(Cache-Control)指令,该缓存可以使用该响应回复之后的请求。但是(如果已经超过最大的指定期限)代理缓存必须优先与服务器进行验证,使用新请求的请求头来允许源服务器验证新请求。(这是s-maxage的定义行为。)如果响应包括“s-maxage=0”,则代理必须总是在重新使用之前对其进行重新验证。

  2.如果响应中包含“must-revalidate”缓存控制指令( cache-control directive),缓存可以在答复后续请求时使用该响应。但是,如果响应已经过期,所有缓存必须首先用源服务器重新验证它,使用来自新请求的请求头来允许源服务器验证新请求。

  3.如果响应包含“public”缓存控制指令,则可以回复任何后续请求。

14.9 Cache-Control

  Cache-Control通用头字段用于指定在请求/响应链上所有的缓存都必须遵守的规则。指令的指定旨在防止缓存对请求或响应产生不利干扰的一些行为。这些指令通常会重写默认缓存算法。缓存指令是单项的,请求中存在指令并不意味着响应中也将会给出相同的指令。

  注意:HTTP/1.0协议版本下的缓存可能无法实现缓存控制,只能实现Pragma(编译指示): no-cache (详情请见 14.32小节).

  缓存指令必须由代理或网关应用程序传递,无论这些指令对该程序是否有用,因为这些指令可能适用于请求/响应链上的所有接收者。我们不可能为特定的缓存指定缓存指令。

      Cache-Control   = "Cache-Control" ":" 1#cache-directive

      cache-directive = cache-request-directive | cache-response-directive

      cache-request-directive =

             "no-cache"                          ; Section 14.9.1

           | "no-store"                          ; Section 14.9.2

           | "max-age" "=" delta-seconds         ; Section 14.9.314.9.4

           | "max-stale" [ "=" delta-seconds ]   ; Section 14.9.3

           | "min-fresh" "=" delta-seconds       ; Section 14.9.3

           | "no-transform"                      ; Section 14.9.5

           | "only-if-cached"                    ; Section 14.9.4

           | cache-extension                     ; Section 14.9.6

       cache-response-directive =

           "public"                               ; Section 14.9.1

                | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1

           | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1

           | "no-store"                             ; Section 14.9.2

           | "no-transform"                         ; Section 14.9.5

           | "must-revalidate"                      ; Section 14.9.4

           | "proxy-revalidate"                     ; Section 14.9.4

           | "max-age" "=" delta-seconds            ; Section 14.9.3

           | "s-maxage" "=" delta-seconds           ; Section 14.9.3

          | cache-extension                        ; Section 14.9.6

    cache-extension = token [ "=" ( token | quoted-string ) ]

  当指令没有任何一个字段名参数出现时,该指令适用于整个请求或响应。当这样的指令以符合要求的字段名参数出现时,它只适用于命名字段,而不适用于请求或响应的其余部分。该机制支持可扩展性;HTTP协议的未来版本的实现可能将这些指令应用于HTTP/1.1中未定义的头字段。

  缓存控制指令可以分解为以下这些一般类别。

    -限制什么是可缓存的;这些只能由源服务器强加。

    -对缓存可以存储的内容的限制;这些可以由源服务器或用户代理强制执行。

    -基本过期机制的修改;这些可以由源服务器或用户代理强制执行。

    -对缓存重新验证和重新加载进行控制;这些可能仅由用户代理强制执行。

    -控制实体的转换。

    -缓存系统的扩展。

14.9.1 What is Cacheable

  默认情况下,如果请求方法、请求头字段和响应状态的指示该响应是可缓存的,则响应是可缓存的。第13.4小节总结了这些可缓存性的默认值。下面的Cache-Control响应指令允许源服务器重写响应的默认缓存性:

public

  指示响应可能由任何缓存来缓存资源,即使它通常不可缓存或仅在非共享缓存中缓存。(请参阅授权,第14.8小节,以了解更多细节。)

private

  指示响应消息的全部或部分用于单个用户,而不能由共享缓存缓存。这允许源服务器声明响应的指定部分仅针对一个用户,而不能对其他用户的请求进行有效响应。私有(非共享)缓存可以缓存响应。

  注意: private一词的在这里的语义只是控制响应可以缓存在哪里,并不能确保消息内容的隐私性。

no-cache

  如果无缓存(no-cache)指令没有指定字段名,则缓存不能使用该响应来满足后续请求,而无需与原始服务器重新验证成功。这允许源服务器甚至通过配置成向客户端请求返回过期响应的缓存来防止缓存。

  如果非缓存指令确实指定了一个或多个字段名,则缓存可以使用响应来满足后续请求,但受缓存上的任何其他限制。但是,在没有与原始服务器成功重新验证的情况下,在响应后续请求时,必须不发送指定的字段名。这允许源服务器防止在响应中重用某些头部字段,同时仍然允许缓存响应的其余部分。

  注意:大部分HTTP/1.0协议下的缓存无法识别或遵守该指令

14.9.2 What May be Stored by Caches

no-store

  no-store指令存在的目的是阻止那些无意间发布或保留的敏感信息(例如,备份信息)。no-store指令为整个消息提供实用,可能会被响应或请求发送。如果在请求中发送,缓存一定不能被请求的任何部分或响应该请求的响应存储。如果在响应中发送,则缓存不能存储该响应的任何部分或引发该请求的请求。该指令也适用于非共享和共享缓存。“必须不存储”在此上下文中意味着缓存必须不故意将信息存储在非易失性存储器中,并且必须尽力在转发信息之后尽可能迅速地从易失性存储器中删除信息。

  即使这个指令与响应相关联,用户也可以在缓存系统之外显式地存储这样的响应(例如,使用“另存为”对话框)。历史缓冲区可以存储这些响应作为正常操作的一部分。

  本指令的目的是满足某些用户和服务作者的既定要求,这些用户和服务作者担心通过意外访问缓存数据结构而泄漏信息。虽然在某些情况下,使用本指令可能改善一些隐私的保密性,但我们警告说,它绝不是确保隐私的可靠或充分的机制。特别地,恶意或受损的缓存可能无法识别或遵从这个指令,并且在这种情况下,通信网络可能很容易被窃听。

14.9.3 Modifications of the Basic Expiration Mechanism

  源服务器可以使用Expires头字段指定实体的过期时间(参见14.21节)。或者,可以在响应中使用max-age指令指定它。当缓存的响应中出现max-age cache-control指令时,如果当前时间大于对该资源的新请求时给出的时间值(以秒为单位),则响应就失效了。响应的max-age指令意味着响应是可缓存的(即,“public”)除非有其他更严格的缓存指令。

  如果一个响应同时包含一个Expires头字段和一个max-age指令,则max-age指令将覆盖Expires头字段,即使Expires头字段有更多的限制。该规则允许源服务器为给定的响应提供比HTTP/1.0缓存更长(或更高)的HTTP/1.1缓存过期时间。如果某些HTTP/1.0缓存无法正确地计算时间或过期时间,这可能是有用的,导致该情况的原因可能是由于时钟不同步。

  许多HTTP/1.0缓存实现会将一个小于或等于响应日期值的Expires值视为等同于cache - control的“no-cache”响应指令。如果HTTP/1.1缓存接收到这样的响应,并且响应不包含cache - control头字段,则应该认为响应不可缓存,以保持与HTTP/1.0服务器的兼容性。

   注意:源服务器可能希望在网络上使用相对较新的HTTP缓存控制特性,比如“private”指令,其中包括不理解该特性的旧缓存。原始服务器需要将新特性与一个Expires字段合并,该字段的值小于或等于日期值。这将防止旧的缓存不正确地缓存响应。

s-maxage

  如果响应包含一个s-maxage指令,那么对于共享缓存(但不是私有缓存),该指令指定的最大使用时限将覆盖由max-age指令或Expires头指定的最大使用时限。s-maxage指令还包含代理重新验证指令的语义(参见14.9.4节),即,在实体过期后,缓存在原始服务器没有重新验证它之前必须不能使用该实体来响应后续请求。私有缓存总是忽略s-maxage指令。

  注意,大多数旧的缓存行为,不遵循这个规范,无法实现任何缓存控制指令。如果源服务器希望使用该限制规范但又不防止HTTP/1.1兼容缓存的cache-control指令,那么它可能会利用max-age指令覆盖Expires头字段的要求,以及HTTP/1.1之前的版本兼容的缓存不遵守max-age指令的事实。

  其他指令允许用户代理修改基本的过期机制。这些指示可按要求指定:

max-age

  指示客户端愿意接受时限不大于指定时间(以秒为单位)的响应。除非还包含了旧的指令,否则客户端不希望接受旧的响应。

min-fresh

  表示客户端愿意接受新鲜度时限不小于当前时间加上指定时间(以秒为单位)的响应。也就是说,客户端希望响应至少在指定的秒数内仍然是有效的。

max-stale

  指示客户端愿意接受超过过期时间的响应。如果赋给max-stale值,那么客户端愿意接受超过其过期时间不超过指定秒数的响应。如果没有赋值给max-stale赋值,那么客户愿意接受任何时限的陈旧响应。

  如果缓存返回陈旧的响应,或者因为请求上的max-stale指令,或者因为缓存被配置为覆盖响应的过期时间,那么缓存必须使用警告110(响应过时了)并将警告标头附加到过时的响应上。

  缓存可以配置为在不进行验证的情况下返回过时的响应,但前提是这与缓存验证的任何“必须”级别需求(例如,“必须重新验证”cache-control指令)不冲突。

  如果新请求和缓存内容都包含“max-age”指令,那么两个值中的较小值将用于确定该请求缓存内容的新鲜度。

14.9.4 Cache Revalidation and Reload Controls

  有时候,用户代理可能希望或需要坚持让缓存使用原始服务器重新验证其缓存条目(而不仅仅是使用沿着原始服务器路径的下一个缓存),或者从原始服务器重新加载其缓存条目。如果缓存或原始服务器高估了缓存响应的过期时间,那么端到端重新验证可能是必要的。如果缓存条目由于某种原因损坏,那么端到端的重新加载可能是必要的。

  端到端重新验证可以在客户端没有自己的本地缓存副本时请求,在这种情况下,我们将其称为“未指定的端到端重新验证”,或者当客户端有本地缓存副本时,在这种情况下,我们将其称为“特定的端到端重新验证”。

  客户端可以使用Cache-Control请求指令指定这三种操作:

End-to-end reload(端到端重新加载)

  这个请求包括一个“无缓存(no-cache)”cache-control指令,或者为了与HTTP/1.0客户端兼容,使用“Pragma: no-cache”。在请求中,字段名不能包含在无缓存指令中。服务器在响应此类请求时不能使用缓存副本。

Specific end-to-end revalidation(特定的端到端重新生效)

  该请求包括一个“max-age=0”cache-control指令,该指令强制沿着到原始服务器的路径中的每个缓存与下一个缓存或服务器一起重新验证自己的条目(如果有的话)。最初的请求包括一个缓存验证条件和客户端的当前验证器。

Unspecified end-to-end revalidation(未指定的端到端再校验)

  该请求包括“max-age=0”缓存控制指令,该指令强制沿着到源服务器的路径的每个缓存使用下一个缓存或服务器重新验证其自己的条目(如果有的话)。初始请求不包括缓存验证条件,沿着保存该资源的缓存条目的路径(如果有的话)的具有其当前验证器的缓存验证条件的第一个缓存。

max-age

  当通过max-age=0指令强制中间缓存重新验证其自己的缓存条目,并且客户端在请求中提供了自己的验证器时,所提供的验证器可能与当前存储在缓存条目中的验证器不同。在这种情况下,缓存可以使用验证器来进行自己的请求,而不影响语义透明性。

  但是,验证器的选择可能会影响性能。最好的方法是中间缓存使用它自己的验证器来进行请求。如果服务器用304(Not Modified.)进行响应,则缓存可以向客户端返回其现在已验证的副本,并带有200(OK)响应。但是,如果服务器用新的实体和缓存验证器进行响应,则中间缓存可以使用强比较函数将返回的验证器与客户端请求中提供的验证器进行比较。如果客户端的验证器等于源服务器,则中间缓存只返回304(Not Modified.)。否则,它返回具有200(OK)响应的新实体。

  如果请求包含no-cache指令,则不应包括min-fresh、max-stale或max-age。

only-if-cached

  在某些情况下,比如网络连接性非常差的时候,客户端可能希望缓存只返回它当前存储的响应,而不是使用原始服务器重新加载或重新验证。要做到这一点,客户端可以在请求中包含noly-if-cached指令。如果它接收到这个指令,缓存应该使用与请求的其他约束一致的缓存条目进行响应,或者使用504(网关超时-Gateway Timeout)状态进行响应。但是,如果一组缓存作为一个统一的系统进行操作,并且具有良好的内部连接,则该请求可以在该组缓存中转发。

must-revalidate(必须重新验证)

  因为缓存可能忽略服务器配置的指定过期时间,因为客户端请求可能包括max-stale指令(也有类似的效果),该协议还包括一个源服务器的机制需要重新验证缓存条目的任何后续使用。当必须重新验证指令出现在缓存接收到的响应中时,该缓存必须在条目过期后使用该条目来响应后续请求,而不优先使用原始服务器重新验证该条目。(即。如果仅基于原始服务器的Expires或max-age值,缓存的响应就过时了,那么每次缓存都必须执行端到端重新验证。)

  must-revalidate指令对于支持某些协议特性的可靠操作是必要的。在任何情况下,HTTP/1.1缓存必须遵守“must-revalidate”指令;特别是,如果缓存由于任何原因无法到达原始服务器,它必须生成504(网关超时)响应。

  服务器应该发送“must-revalidate”指令,当且仅当在实体上重新验证请求失败可能导致错误操作(如未执行的财务事务)时才发送该指令。接收方不得采取任何违反此指令的自动操作,也不得在重新验证失败时自动提供实体的未验证副本。

  尽管不建议这样做,但是在严格的连接约束下操作的用户代理可能违反此指令,但如果是这样,则必须明确警告用户已经提供了未经验证的响应。每个未经验证的访问都必须提供警告,并且需要明确的用户确认。

proxy-revalidate(代理重新验证)

  proxy-reavalidate指令的含义与must-revalidate指令相同,只是它不适用于非共享的用户代理缓存。提供每次重新验证的服务(为了确保每个用户已经通过身份验证)。

它可以使用在回应一个身份验证请求,允许用户的缓存来存储和后来返回响应,而不需要重新验证(因为它已经被该用户身份验证一次),同时还要求代理服务许多用户重新验证每一次(为了确保每个用户已经通过身份验证)。注意,这种经过身份验证的响应还需要“public”缓存控制指令,以便能够完全缓存它们。

14.9.5 No-Transform Directive

no-transform

  中间缓存(代理)的实现者发现转换某些实体的媒体类型是有用的。例如,非透明代理可以在图像格式之间进行转换,以便节省缓存空间或减少慢速链路上的通信量。

  然而,当这些转换应用于特定类型的应用程序实体时,会出现严重的操作问题。例如,用于医学成像、科学数据分析以及使用端到端认证的应用都依赖于接收与原始实体-主体逐位相同(bit for bit identical——也就是每一字节都与原实体一样)的实体主体。

  因此,如果消息包括no-transform指令,则中间缓存或代理必须不改变那些在第13.5.2节中列出的、受no-transform指令制约的报头。这意味着缓存或代理必须不改变由这些头字段指定的实体主体的任何方面,包括实体主体本身的值。  

14.9.6 Cache Control Extensions

  可以通过使用一个或多个缓存扩展令牌来扩展Cache-Control头字段,每个令牌具有可选的分配值。可以在不改变其他指令的语义的情况下添加信息扩展(不需要改变缓存行为的扩展)。行为扩展被设计为通过对缓存指令的现有基础作为修饰符来工作。提供新的指令和标准指令,使得不理解新指令的应用程序将默认执行标准指令指定的行为,而理解新指令的应用程序将认识到它修改了与标准指令相关的需求。这样,可以在不修改基础协议的情况下,对缓存控制指令进行扩展。

  这种扩展机制依赖于HTTP缓存,它遵守为其原生HTTP版本定义的所有缓存控制指令,遵守某些扩展,并忽略它不理解的所有指令。

  例如,假设有一个名为community的新响应指令,它充当私有指令的修饰符。我们定义这个新指令是为了表示,除了任何非共享缓存之外,任何仅由值中指定的社区成员共享的缓存都可以缓存响应。希望允许UCI社区在其共享缓存中使用私有响应的源服务器可以通过包括下面的字段来实现这一点

       Cache-Control: private, community="UCI"

  即使缓存不理解community cache-extension,看到这个header字段的缓存也会正常工作,因为它也会看到并理解私有指令,因此默认为安全行为。

  不能识别的缓存指令必须被忽略;假设任何缓存指令可能无法被HTTP/1.1缓存识别,将与标准指令结合使用(或者响应的默认缓存能力,即使缓存不理解扩展,缓存行为也将保持最低限度的正确性)。

14.10 Connection

  Connection通用头字段允许发送方指定特定链接所需的选项,并且代理不能通过其他链接进行通信。

  Connection头字段的语法如下:

         Connection = "Connection" ":" 1#(connection-token)

         connection-token  = token

  在Connection字段中列出的Message头字段不能包含端到端类型的头字段,比如Cache-Control。  

  HTTP/1.1为发送方定义了“close”连接选项,以表示连接将在响应完成后关闭。比如:

         Connection: close

  无论在响应还是请求中都表示在响应或请求完成后,该链接不能被当作持久链接。

  不支持持久链接的HTTP/1.1应用程序必须在每一个消息(message)中包含close链接选项。

  接收包含Connection头字段的HTTP/1.0(或较低版本)消息的系统,对于该字段中的每个连接令牌(coonection-token),必须从与连接令牌同名的消息中删除和忽略任何头字段。这可以防止这些头字段被http /1.1代理错误转发。(详情见19.6.2小节)

14.11 Content-Encoding

  Content-Encoding实体头字段被用来当作media-type的调节器。当存在时,它的值指示哪些附加的内容编码已经应用到实体主体,因此我们要知道在Content-Type头字段中使用的media-type需要使用怎么样的解码机制。Content-Type主要用于允许文档被压缩而不丢失其底层媒体类型的特征。

       Content-Encoding  = "Content-Encoding" ":" 1#content-coding

  内容编码在 3.5中被定义。一个使用的例子:

       Content-Encoding: gzip

  内容编码是由请求URI标识的实体的特性。典型地,实体用这样的编码方式存储,并且只有在渲染内容或类似的情况下使用之前才被解码。然而,除非消息中存在“no-transform”缓存控制指令,否则,如果已知接收方可以接受新编码,则非透明代理可以修改内容编码。

  如果一个实体的内容编码不是“identity”,然后,响应必须包含内容编码实体头(14.11节),其中列出了使用的非标识内容编码。

  如果原始服务器无法接受请求消息中实体的内容编码,则服务器应以状态码415(Unsupported Media Type)进行响应。

  如果多个编码被应用到一个实体中,内容编码必须按照应用它们的顺序列出。有关编码参数的其他信息可以由本规范未定义的其他实体头字段提供。

14.12 Content-Language

  Content-Language 实体头字段描述了封闭实体的预期受众的自然语言。注意,这可能不等于实体主体(entity-body)中使用的所有语言。

         Content-Language  = "Content-Language" ":" 1#language-tag

  语言标识在 3.10节中做了定义。内容语言的主要目的是允许用户根据自己的首选语言识别和区分实体。因此,如果正文内容仅针对具有丹麦语文化的读者,则适当的范围是

         Content-Language: da

  如果没有指定内容语言,默认情况下内容是针对所有语言受众的。这可能意味着发送方不认为它是特定于任何自然语言的,或者发送方不知道它是针对哪种语言的。

  可以为多个受众列出多个语言的内容。例如,同时在原始毛利语和英语版本中出现的《瓦伊坦吉条约》的译本就需要

         Content-Language: mi, en

  然而,仅仅因为多个语言存在于一个实体中并不意味着它是针对多个语言受众的。举个例子,初学者的语言入门,比如“拉丁语第一课”,很明显是用来让有英语基础的观众使用的。在这种情况下,内容语言将只包括“EN”。

  Content-Language可以应用于任何媒体类型——它不限于文本文档。

14.13 Content-Length

  Content-Length实体头字段表示实体内容的大小,发送给接收者的是一个十进制八位字节的数字,在HEAD方法中,如果请求是GET,那么将发送的实体主体的大小。

         Content-Length    = "Content-Length" ":" 1*DIGIT

  下面是一个例子

         Content-Length: 3495

  应用程序应该使用此字段来指示消息体的传输长度(transfer-length),除非第4.4节中的规则禁止这一点。

  任何大于或等于0的内容长度都是一个有效值。第4.4节描述了如果没有提供内容长度,如何确定消息体的长度。

  注意,这个字段的含义与MIME中相应的定义有很大的不同,MIME是“消息/外部体”("message/external-body")内容类型中使用的可选字段。在HTTP中,只要消息的长度可以在传输之前确定,就应该发送它,除非第4.4节中的规则禁止这一点。

14.14 Content-Location

  当从与请求资源的URI分离的位置访问该实体时,可以使用Content-Location实体头字段为消息中包含的实体提供资源位置。服务器应该为响应实体对应的变体提供内容位置;特别是当一个资源有多个与它相关联的实体,并且这些实体实际上有单独的位置,通过这些位置可以单独访问它们,服务器应该为返回的特定变体提供一个内容位置。

        Content-Location = "Content-Location" ":"( absoluteURI | relativeURI )

  Content-Location的值也定义了基本实体的URI。

  Content-Location的值不是原始请求URI的代替;它只是请求时对应于此特定实体的资源位置的声明。如果希望标识特定实体的源,将来的请求可以指定Content-Location URI作为请求URI。

  缓存不能假设具有与用于检索它的URI不同的内容位置的实体可以用于响应该内容位置URI上的稍后请求。然而,Content-Location可用于区分从单个请求资源检索的多个实体,如第13.6节所述。

  如果Content-Location是一个相对的URI标识,相对URI是相对于请求URI解释的。

  在PUT或Post请求中Content-Location头字段是未定意的。服务器在这种情况下会忽略这些内容。

14.15 Content-MD5

  RFC 1864中定义的Content-MD5实体头字段是实体主体的MD5摘要,用于提供实体主体的端到端消息完整性检查(MIC)。(注意:MIC用于检测传输中的实体主体的意外修改,但不能防止恶意攻击。)

          Content-MD5   = "Content-MD5" ":" md5-digest

          md5-digest   = <base64 of 128 bit MD5 digest as per RFC 1864>

  Content-MD5头字段可以由源服务器或客户端生成,以作为实体主体的完整性检查。只有原始服务器或客户端可能生成Content-MD5头字段;代理和网关不能生成,因为这将破坏其作为端到端完整性检查的价值。任何实体主体的接收者,包括网关和代理,都可以检查这个头字段中的摘要值是否与接收到的实体主体的摘要值匹配。

  MD5摘要是基于实体主体的内容计算的,包括已经应用的任何内容编码,但不包括应用到消息主体的任何传输编码。如果用传输编码接收到消息,则必须在根据接收到的实体检查Content-MD5值之前删除该编码。

  这样做的结果是,在实体主体的八位字节上精确地计算摘要,并且如果没有应用传输编码,则按照这样的顺序发送摘要。

  HTTP扩展了RFC 1864,允许为MIME复合媒体类型(例如,multipart/*和message/rfc822)计算摘要,但这并不改变如前段所定义的摘要的计算方式。

  这有几个后果。复合类型的实体主体可能包含许多主体部分,每个部分都有自己的MIME和HTTP头(包括Content-MD5、Content-Transfer-Encoding和Content-Encoding头)。如果body-part具有content - transfer - encoding头字段,则假设body-part的内容已经应用了编码,并且body-part包含在content - md5摘要中,如下所示:之后的运行中。在主体部分中不允许使用Transfer-Encoding头字段。

  在计算或检查摘要之前,不能将所有换行符转换为CRLF:实际传输的文本中使用的换行约定在计算摘要时必须保持不变。

  注意:尽管Content-MD5的定义对于HTTP与RFC 1864对于MIME实体主体的定义完全相同,但是在几种情况下,Content-MD5对于HTTP实体主体的应用不同于其对于MIME实体主体的应用。一种是HTTP不同于MIME,它不使用内容传输编码,但使用传输编码和内容编码。另一个原因是HTTP比MIME更频繁地使用二进制内容类型,因此值得注意的是,在这种情况下,用于计算摘要的字节顺序是为该类型定义的传输字节顺序。最后,HTTP允许使用几种换行规则中的任何一种来传输文本类型,而不仅仅是使用CRLF的规范形式。

14.16 Content-Range

  Content-Range实体头字段与部分实体主体一起发送,以指定在完整实体主体中应该在何处应用部分主体。范围单元在3.12节中定义。

         Content-Range = "Content-Range" ":" content-range-spec

         content-range-spec          =  byte-content-range-spec

         byte-content-range-spec  =  bytes-unit SP

                                         byte-range-resp-spec "/"  ( instance-length | "*" )

         byte-range-resp-spec    = (first-byte-pos "-" last-byte-pos)  | "*"

         instance-length                = 1*DIGIT

  报头应该指示完整实体的总长度,除非这个长度是未知的或难以确定的。星号“*”字符表示在生成响应时,实例长度未知。

  与byte-ranges-specifier的值(参见14.35.1节)不同,byte-range-resp-spec必须只指定一个范围,并且必须包含该范围的第一个和最后一个字节的绝对字节位置。

  当一个byte-range-resp-spec存在一个byte-content-range-spec值,并且该值的最后一位(last-byte-pos)小于它的第一位(first-byte-po),或者它的实际长度(instance-length)小于或等于它最后一位(last-byte-pos),这样是不允许的。接收者应该忽略一个未通过验证的byte-content-range-spec,以及随其传输的任何其他内容。

  发送具有状态代码416(请求范围不可满足)的响应的服务器应该包括具有byte-range-resp-spec的值为“*”的Content-Range字段。实例长度指定所选资源的当前长度。使用状态代码206(部分内容)的响应不能包含具有“*”字节的 byte-range- resp-spec字段。  

  下面是一个字节内容范围规则值(byte-content-range-spec)的例子,假设实体总共包含了1234字节:

        . 最开始的500个字节: bytes 0-499/1234

        . 第二个五百个字节: bytes 500-999/1234

        . 除了前五百个字节: bytes 500-1233/1234

        . 最后五百个字节: bytes 734-1233/1234

  当一个HTTP消息包含一个单一范围的内容(例如,一个响应请求一个单一的范围,或者请求一组没有任何漏洞的重叠范围),该内容与Content-Range头字段一起传递,并且Content-Length头字段应该显示实际传输的字节数。例如,

         HTTP/1.1 206 Partial content

         Date: Wed, 15 Nov 1995 06:25:24 GMT

         Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT

         Content-Range: bytes 21010-47021/47022

         Content-Length: 26012

         Content-Type: image/gif

  当HTTP消息包含多个范围(例如,对多个非重叠范围的请求的响应)的内容时,这些内容作为多部分消息进行传输。用于此目的的大部分媒体类型是附录19.2中定义的“多multipart/byteranges”。兼容性问题见附录19.6.3

  对于单个范围的请求的响应不能使用multipart/byteranges媒体类型来发送。对多个范围的请求的响应,如果其结果是单个范围,可能作为带有一个部分的multipart/byteranges媒体类型发送。不能解码multipart/byteranges消息的客户端不能在单个请求中请求多个byte-ranges。

  当客户端在一个请求中请求多个byte-ranges时,服务器应该按照它们在请求中出现的顺序返回它们。

  如果服务器由于语法无效而忽略了 byte-range-spec,则服务器应将请求视为不存在无效Range头字段。(通常,这意味着返回包含完整实体的200响应)。

  如果服务器收到一个请求(除了一个包括If-Range请求头字段)和一个请求头字段不可满足的范围(即所有的byte-range-spec值first-byte-pos值大于当前选中的资源的长度),它应该返回一个416响应代码(请求的范围不可以满足的)( 10.4.17小节)。

  注意:对于不可满足Range请求头字段情况,客户端不能依赖服务器发送416(Requested range not satisfiable)响应来代替200 (OK)响应,因为不是所有服务器都支持这个请求头。

14.17 Content-Type

  Content-Type实体字段表示发送给接收方的实体主体的媒体类型,对于HEAD方法,则表示如果请求是GET,应该发送的媒体类型。

         Content-Type   = "Content-Type" ":" media-type

   媒体类型已经在 3.7小节中定义,下面是该字段的一个例子

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

  第7.2.1节进一步讨论了确定实体的媒体类型的方法。

14.18 Date

  Date通用头字段表示消息产生的日期和时间,跟RFC822中的orig-date一样。该字段的值是一个HTTP—DATE,它的详细描述在 3.3.1小节,它在传输的时候必须被格式化。

         Date  = "Date" ":" HTTP-date

  下面是一个例子:

         Date: Tue, 15 Nov 1994 08:12:31 GMT

  源服务器必须在所有的响应中包含一个Date头字段,除了以下的情况:

    1.如果响应的状态码是100或者101,在服务器的配置中,响应中可以包含Date头字段。

    2.如果响应状态代码传递了一个服务器错误,例如500(内部服务器错误)或503(服务不可用),并且不方便或不可能生成一个有效的日期。

    3.如果服务器没有一个可以提供合理的接近当前时间的值,那么它的响应一定不能包含一个Date头字段,我们必须遵守 14.18.1小节中的相关规则。

  如果消息将通过需要Date的协议被接收方或网关缓存,则接收到的没有日期标头字段的消息必须由接收方分配一个Date头字段。没有时钟的HTTP实现不能缓存响应,并且不必在每次使用时重新验证它们。HTTP缓存,尤其是共享缓存,应该使用NTP等机制来使其时钟与可靠的外部标准同步。

  客户端应该只在包含entity-body的消息中发送Date头字段,就像PUT和POST请求那样,即使这样,它也是可选的。没有时钟的客户端不能在请求中发送Date头字段。

  在日期标头中发送的HTTP-date不应该表示消息生成之后的日期和时间。它应该表示消息生成时日期和时间的最佳近似值,除非实现无法生成合理准确的日期和时间。理论上,日期应该表示实体生成之前的时刻。在实践中,日期可以在不影响其语义值的情况下,消息发起期间的任何时候生成。

14.18.1 Clockless Origin Server Operation

  一些原始服务器实现可能没有可用的时钟。没有时钟的原始服务器不能给响应分配Expires或Last-Modified值,除非Date值是由与资源相关联的、具有可靠时钟的系统或用户产生的。它可能分配一个Expires值,该值在服务器配置时或之前是已知的(这使得“pre-expiration”的响应无需单独的存储每个资源的Expires值)。

14.19 ETag

  ETAG响应头字段为所请求的变体提供实体标签的当前值。在 14.2414.26 14.44小节中描述了与实体标签一起使用的头字段。实体标签可用于与来自同一资源的其他实体进行比较(参见第13.3.3节)。

        ETag = "ETag" ":" entity-tag

  例子:

        ETag: "xyzzy"

        ETag: W/"xyzzy"

        ETag: ""

14.20 Expect

  Expect请求头字段被用来描述客户端需要的特定的服务器行为。

        Expect       =  "Expect" ":" 1#expectation

        expectation  =  "100-continue" | expectation-extension

        expectation-extension =  token [ "=" ( token | quoted-string ) *expect-params ]

        expect-params =  ";" token [ "=" ( token | quoted-string ) ]

  服务器如果无法理解或者遵守任何请求中Expect头字段中的任何存在的预期值,那么应该返回适当的错误状态。服务器必须返回417错误,如果任何的“期望”都无法满足,或者有其他的客户端请求错误,一些4XX错误。

  该头字段被定义为可扩展的语法,以用在未来可能的扩展中。如果一个服务器接收到了它不支持的Expect头字段中所包含的拓展词(expectation-extension),那么它必须返回一个417错误(Expectation Failed)。

  “期望”值的比较对于未引用的tokens(包括100-continue)不区分大小写,并且对于引用字符串的期望扩展区分大小写。

  Expect机制是逐跳(hop-by-hop)的:也就是说,如果HTTP/1.1代理接收到了预期无法满足的请求,则必须返回417(Expectation Failed)状态。但是,预期请求头本身是端到端的;如果转发请求,则必须转发它。

  许多较老的HTTP/1和HTTP/1.1应用程序不理解Expect头字段。

  100(continue)状态码的使用方法请查阅8.2.3小节。

14.21 Expires

  Expires实体头字段给出响应过期的日期/时间。过期的缓存内容通常不会返回缓存机制所缓存的内容(包括代理缓存或用户代理缓存),除非它首先通过原始服务器(或具有实体的新副本的中间缓存)进行验证。有关到期模型的进一步讨论,请参阅第 13.2节。

  Expires字段的存在并不意味着原始资源将在该时间节点点之前或之后改变或不再存在。

  该字段值的格式是由3.3.1节中的HTTP日期定义的绝对日期和时间;它必须是RFC 1123日期格式:

10-11 18:16