大家好,又见面了,我是你们的朋友全栈君。
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.3, 14.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.24, 14.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日期格式:
Expires = “Expires” “:” HTTP-date
下面是一个使用案例
Expires: Thu, 01 Dec 1994 16:00:00 GMT
注意:如果响应包含一个Cache-Control字段和max-age指令(参见14.9.3节),该指令将覆盖Expires字段。
HTTP/1.1客户端和缓存必须处理其他无效的日期格式,特别是包含“0”的值(例如“已过期”)。
如果想要将响应标记为“已过期”,那么源服务器需要发送一个等于日期标头值的过期日期。(详情请参阅第 13.2.4节中的过期计算规则。)
为了将响应标记为“永不过期”,源服务器发送的Expires日期的值为该响应发送时起的一年后,那么HTTP/ 1.1服务器不应在未来发送超过一年的过期日期。
如果Expires头字段的日期值在将来的某个时间出现在默认为不可缓存的响应上,那么表示响应是可缓存的,除非Cache-Control头字段( 14.9小节)另有指示。
14.22 From
From请求头字段,如果存在,需要包含一个客户端使用者的互联网邮箱地址。该地址应该是可以被机器识别的“machine-usable”,具体的规则在 RFC 822 [9]并在 RFC 1123 [8]中做了一些升级:
From = “From” “:” mailbox
下面是一个例子:
From: webmaster@w3.org
该头字段可用于日志记录,并可用于标识无效或不想要请求的资源。它不应该用作不安全的访问保护形式。该字段的解释是,请求是代表指定的人所发出的,该人对执行方法负有责任。特别是,机器人代理应该包括这个头,以便在接收端出现问题时可以联系负责运行机器人的人。
此字段中的Internet电子邮件地址可能与发出请求的Internet主机分开。例如,当请求通过代理传递时,应该使用原始发布者的地址。
客户端不应该在未经用户批准的情况下发送From头字段,因为这可能会与用户的隐私利益或其站点的安全策略发生冲突。强烈建议用户能够在请求之前的任何时候禁用、启用和修改此字段的值。
14.23 Host
Host 请求头字段指定了从用户给出的原始URI或引用资源(通常是HTTP URL,如3.2.2节所述)中所获得的被请求资源的网络主机和端口号。HOST字段值必须代表原始URL给出的源服务器或网关的命名权限。这允许原始服务器或网关区分内部模糊的(内部歧义)URL,例如,用于单个IP地址上的多个主机名的服务器URL的根名称“/”。
Host = “Host” “:” host [ “:” port ] ; Section 3.2.2
如果一个host尾部并没有跟随端口号信息,那么就是默认的端口号(比如,HTTP URl的默认端口号是80)。举个例子。向“http://www.w3.org/pub/WWW”所发出的请求会包含以下信息:
GET /pub/WWW/ HTTP/1.1
Host: www.w3.org
在HTTP/1.1的客户端请求信息中必须包含HOST头字段。如果所请求的URI不包括所请求服务的Internet主机名,则必须给Host头字段一个空值。HTTP/1.1代理必须确保它转发的任何请求信息中都包含适当的HOST头字段,该字段标识代理请求的服务。所有基于HTTP/1.1的互联网请求的服务器必须对任何缺少主机头字段的HTTP/1.1请求消息使用400(Bad Request)状态码进行响应。
有关HOST字段的其他要求见第5.2和19.6.1.1 节。
14.24 If-Match
If-Match请求头字段需要与一个使其成为“条件”的方法一起使用。拥有一个或多个之前从资源中获得的实体的客户端可以通过在If-Match头字段中包含相关实体标记的列表来验证这些实体中的一个是否是当前匹配的。实体标记在 3.11节中有详细说明。这个特性的目的是允许以最少的开销,高效地更新缓存的信息。在更新请求时,它还用于防止无意中修改错误版本的资源。作为一种特殊情况,“*”值匹配资源的任何当前实体。
If-Match = “If-Match” “:” ( “*” | 1#entity-tag )
如果任何实体标记与在响应该资源上的类似GET请求(没有if-Match头字段)时返回的实体的实体标记相匹配,或者如果“*”值在IF-Matc中被给出并且任何当前的实体都存在该资源中,则服务器可以执行所请求的方法就像if-Match头字段不存在一样。
服务器必须使用强比较函数(参见第 13.3.3节)来比较If-Match中的实体标签。
如果没有匹配的实体标记,或者给定了“*”值,且不存在当前实体,服务器就不能执行请求的方法,必须返回412(Precondition Failed)响应。当客户端希望阻止一个更新类型的方法(如PUT)修改自客户端上次检索后已更改的资源时,这种行为最有用。
如果请求在没有if-Match头字段的情况下会导致除了2xx或412状态之外的任何结果,则必须忽略if-Match头字段。
“if-Match:*”的含义是,如果源服务器(或缓存,可能使用变体机制,请参见14.44节)选择的内容存在,则应该执行该方法,如果内容不存在,则必须不执行该方法。
更新资源(例如PUT)的请求可能包含if-match头字段,以表示如果与if-match值(单个实体标记)对应的实体不再是该资源的表示,则不得应用请求方法。这允许用户表示,如果资源在他们不知情的情况下被更改,他们不希望请求成功。
例如:
If-Match: “xyzzy”
If-Match: “xyzzy”, “r2d2xxxx”, “c3piozzzz”
If-Match: *
一个请求中是否可以同时存在If-Match字段和If-None-Match或If-Modified-Since头字段在本规范中并未定义。
14.25 If-Modified-Since
If-Modified-Since请求头字段需要与一个使其成为“条件”的方法一起使用:如果请求变量在该字段给出的时间范围内没有被修改,那么服务器则不能返回实体内容。替代的,一个没有任何信息体的304(Not Modified)响应会被返回。
If-Modified-Since = “If-Modified-Since” “:” HTTP-date
下面是该字段的一个例子:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
一个带有If-Modified-Since头字段且没有Range头字段的GET方法只要求标识的实体在If-Modified-Since头字段给出的日期之后被修改,才会被传递。确定这一点的算法包括下列情况:
a) 如果请求通常不会导致200 (OK)状态,或者传递的If-Modified-Since日期无效,则响应与普通GET完全相同。晚于服务器当前时间的日期无效。
b) 如果该变体自If-Modified-Since所携带的日期以来进行了修改,则响应与普通GET完全相同。
c)如果该变体在有效的If-Modified-Since日期之后没有被修改,服务器应该返回304(没有修改)响应。
这个特性的目的是允许以最少的事务开销来更高效地更新缓存的信息。
注意:Range请求头字段会修改If-Modified-Since的含义。详情请见14.35小节。
注意:因为时间是由服务器确定的,服务器的时间可能与客户端的时间不同步。
注意:在处理If-Modified-Since头字段时,一些服务器将使用精确的日期比较函数而不是小于函数来决定是否发送304(未修改)响应。为了获得最好的结果,当发送一个If-Modified-Since头字段来进行缓存验证时,建议客户端尽可能使用在上一个Last-Modified头字段中收到的确切日期字符串。
注意:如果客户端在If-Modified-Since头字段中使用任意日期,而不是使用从同一个请求的Last-Modified头字段中提取的日期,那么客户端应该知道这个日期是用服务器中的时间来做为解释的。由于客户端和服务器之间的时间并不相同,客户端需要考虑不同步时钟和舍入问题。这包括,如果文档在第一次请求的时间和后续请求中存在If-Modified-Sinc日期之间发生了更改,那么可能存在竞态条件;如果If-Modified-Since日期来自客户端的时钟,且并没有修改服务器的时钟,则可能存在时钟偏移相关的问题。由于网络延迟,客户端和服务器之间的不同时间间隔即使在修正后也不可能完全一样。
一个请求中是否可以同时存在If-Match字段和If-None-Match或If-Modified-Since头字段在本规范中并未定义。
14.26 If-None-Match
If-None-Match请求头字段需要与一个使其成为“条件”的方法一起使用。拥有一个或多个先前从资源中获得的实体的客户端可以通过在If-None-Match头字段中包含相关实体标记的列表来验证这些实体都不是当前的。这个特性的目的是允许以最少的事务开销来高效地更新缓存的信息。它还用于防止客户端认为资源不存在时在无意中使用一些方法修改现有资源(例如PUT)。
作为一种特殊情况,“*”值匹配资源的任何当前实体。
If-None-Match = “If-None-Match” “:” ( “*” | 1#entity-tag )
如果任何实体标记匹配该实体标记,那么将会导致在使用一个类似GET请求(不具有If-None-Match请求头)下的资源被返回,或者给出的If-None-Match请求头字段的值时*号并且当前存在任何属于该资源的实体,除非必要否则服务器一定不能执行所请求的方法,因为在If-Modified-Since请求头字段中资源的修改日期是不匹配的。。相反,如果请求方法是GET或HEAD,服务器应该使用304(未修改)响应进行响应,包括与缓存相关的头字段(特别是与ETag匹配的一个实体)。对于所有其他请求方法,服务器必须以412状态响应(Precondition Failed)。
有关如何确定两个实体标记是否匹配的规则,请参阅第13.3.3节。弱比较函数只能用于GET或HEAD请求。
如果实体标记都不匹配,那么服务器可以执行请求的方法,就好像If-None-Match头字段不存在一样,但是必须忽略请求中存在的任何If-Modified-Since头字段。也就是说,如果没有实体标记匹配,服务器就不能返回304(Not Modified)响应。
如果请求在没有If-None-Match头字段的情况下,结果不是2xx或304状态,则必须忽略If-None-Match标头。(请参阅第13.3.4节,了解在同一请求中同时出现If-Modified-Since和If-None-Match时的服务器行为。)
“If-None-Match: *”的意思是,如果原始服务器(或缓存可能使用变体机制,请参见14.44节)选择的表示存在,则不能执行该方法,如果表示不存在,则应该执行该方法。这个特性用于防止PUT操作之间的竞争。
例子:
If-None-Match: “xyzzy”
If-None-Match: W/”xyzzy”
If-None-Match: “xyzzy”, “r2d2xxxx”, “c3piozzzz”
If-None-Match: W/”xyzzy”, W/”r2d2xxxx”, W/”c3piozzzz”
If-None-Match: *
一个请求中是否可以同时存在If-Match字段和If-None-Match或If-Modified-Since头字段在本规范中并未定义。
14.27 If-Range
如果客户端在其缓存中有一个实体的部分副本,并且希望在其缓存中有整个实体的最新副本,那么它可以使用Range 请求头和一个有条件的GET(使用If-Unmodified-Since和If-Match)。但是,如果由于实体被修改而导致条件失败,那么客户端将不得不发出第二次请求以获得整个当前实体主体。
If-Range报头允许客户端“短路(short-circuit)”第二个请求。非正式地说,它的意思是“如果实体没有改变,就把我缺少的部分发给我;否则,将整个新实体发送给我”。
If-Range = “If-Range” “:” ( entity-tag | HTTP-date )
如果客户端没有实体的实体标记,但是有最后修改日期,它可以在If-Range头字段中使用该日期。(服务器可以通过检查不超过两个字符来区分有效的HTTP-date和任何形式的实体标记。)If-Range头字段应该只与Range头字段一起使用,如果请求不包含Range头字段,或者服务器不支持子范围操作,则必须忽略该报头。
If the entity tag given in the If-Range header matches the current entity tag for the entity, then the server SHOULD provide the specified sub-range of the entity using a 206 (Partial content) response. If the entity tag does not match, then the server SHOULD return the entire entity using a 200 (OK) response.
如果If-Range头字段中的实体标记与实体的当前实体标记匹配,那么服务器应该使用206(Partial content)响应提供实体的指定子范围。如果实体标记不匹配,那么服务器应该使用200 (OK)响应返回整个实体。
14.28 If-Unmodified-Since
If-Unmodified-Since请求头字段需要与一个使其成为“条件”的方法一起使用。如果请求的资源在此字段中指定的时间之后没有被修改,服务器应该执行请求的操作,就像If-Unmodified-Sincee头文件不存在一样。
如果请求的变体自指定时间以来已经被修改,服务器必须不执行请求的操作,并且必须返回412(Precondition Failed)状态。
If-Unmodified-Since = “If-Unmodified-Since” “:” HTTP-date
下面是该字段的一个例子:
If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
如果在请求正常(例如,请求中没有If-Unmodified-Since报头)的情况下,,可能会产生除了2xx或412状态外的其他任何状态,那么If-Unmodified-Since报头应该被忽略。
如果指定的日期无效,则忽略该头字段。
此规范未定义具有If-Unmodified-Since标头字段和If-None-Match或If-Modified-Since标头字段的请求的结果。
14.29 Last-Modified
Last-Modified实体头字段指示原始服务器认为该变体最后被修改的日期和时间。
Last-Modified = “Last-Modified” “:” HTTP-date
下面是该字段的是个用法例子:
Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
这个头字段的确切含义取决于原始服务器的实现和原始资源的性质。对于文件,可能只是文件系统最后一次修改的时间。对于包含动态部件的实体,它可能是其组件部件的最后一次修改时间集的最近一次修改时间集。对于数据库网关,它可能是记录的最后更新时间戳。对于虚拟对象,可能是最后一次更改的内部状态。
源服务器不能发送晚于服务器发出消息时间的Last-Modified日期。在这种情况下,如果资源的最后一次修改将指示将来的某个时间,则服务器必须将该日期替换为消息发起日期。
原始服务器应该包含尽可能接近于实体生成响应的时间的日期值的Last-Modified值。这允许接收方准确评估实体的修改时间,特别是当实体在生成响应时发生更改。
HTTP/1.1服务器应该在可行的情况下发送Last-Modified。
14.30 Location
Location 响应头字段用于将收件人重定向到请求uri以外的位置,以完成请求或标识新资源。对于201(Created)响应,Location是由请求创建的新资源的位置。对于3xx响应,Location应该指示服务器自动重定向到资源的首选URI。字段值由单个绝对URI组成。
Location = “Location” “:” absoluteURI
例子:
Location: http://www.w3.org/pub/WWW/People.html
注意:Content-Location头字段(14.14节)与Location不同,因为Content-Location标识了请求中包含的实体的原始位置。因此,响应可以包含Location和Content-Location的头字段。某些方法的缓存要求参见第13.10节。
14.31 Max-Forwards
Max-Forwards请求头字段为TRACE(9.8节)和OPTIONS(9.2节)方法提供了一种机制,用于限制可以将请求转发到下一个入站服务器的代理或网关的数量。当客户端试图跟踪请求链时,如果请求链在中间链中出现故障或循环,这可能非常有用。
Max-Forwards = “Max-Forwards” “:” 1*DIGIT
最大转发值是一个十进制整数,指示此请求消息可能被转发的剩余次数。
TRACE或OPTIONS请求的每个代理或网关接收者(包含Max-Forwards头字段)必须在转发请求之前检查并更新其值。如果接收到的值为0,接收方不得转发请求;相反,它必须作为最终接收者做出回应。如果接收到的Max-Foewards值大于零,那么转发的消息必须包含一个更新的Max-Foewards字段,其值递减为1。
对于本规范中定义的所有其他方法和那些没有明确地将其作为该方法定义的一部分的扩展方法来说,Max-Forwards头字段都可能被忽略。
14.32 Pragma
Pragma通用头字段用于包含可能应用于请求/响应链上任何接收者的特别的指令。所有实用程序指令从协议的角度指定可选行为;然而,一些系统可能要求行为与指令一致。
Pragma = “Pragma” “:” 1#pragma-directive
pragma-directive = “no-cache” | extension-pragma
extension-pragma = token [ “=” ( token | quoted-string ) ]
当请求消息中出现no-cache指令时,应用程序应该将请求转发到原始服务器,即使它有被请求内容的缓存副本。这个pragma指令具有与no-cache缓存指令相同的语义(参见14.9节),它的定义是为了向后兼容HTTP/1.0。当一个没有缓存的请求被发送到一个不知道是否兼容HTTP/1.1的服务器时,客户端应该包含这两个头字段。
Pragma指令必须通过代理或网关应用程序传递,而不管它们对应用程序的重要性如何,因为这些指令可能适用于请求/响应链上的所有接收者。不可能为特定的接收者指定一个实用程序;然而,任何与接收者无关的Pragma指令都应该被接收者忽略。
HTTP/1.1缓存应该将“Pragma: no-cache”视为客户端发送的“Cache-Control: no-cache”。HTTP中不会定义新的Pragma指令。
注意:因为“Pragma: no-cache”作为响应头字段的含义实际上没有指定,所以它不能替换响应中的“Cache-Control: no-cache”头字段。
14.33 Proxy-Authenticate
Proxy Authenticate 响应头字段必须被包含在一个407(Proxy Authentication Required)响应中。字段值包含一个“询问”,该“询问”指示这个请求URI的代理适用的身份验证方案及参数。
Proxy-Authenticate = “Proxy-Authenticate” “:” 1#challenge
HTTP访问身份验证过程被描述为“HTTP身份验证:基本和摘要访问身份验证”[43]。与WWW-Authenticate不同,代理身份验证头字段仅应用于当前连接,不应传递到下游客户端。但是,中间代理可能需要通过从下游客户端请求它们来获得自己的凭证,在某些情况下,这看起来就好像代理在转发Proxy-Authenticate头字段一样。
14.34 Proxy-Authorization
Proxy-Authorization请求头字段允许客户端将自己(或其用户)标识给需要身份验证的代理。Proxy-Authorization字段值由凭证组成,该凭证包含用户代理的身份验证信息,用于请求的资源和/或领域。
Proxy-Authorization = “Proxy-Authorization” “:” credentials
HTTP访问身份验证过程在“HTTP Authentication:基本和摘要访问身份验证”[43]中有更详细的描述。与Authorization不同,Proxy-Authorization头字段仅适用于使用Proxy- Authenticate字段要求进行身份验证的下一个出站代理。当在一个链中使用多个代理时,Proxy-Authorization头字段将由第一个期望接收凭证的出站代理使用。代理可以将凭证从客户端请求中继到下一个代理,如果这是代理合作验证给定请求的机制的话。
14.35 Range
14.35.1 Byte Ranges(字节范围)
由于所有HTTP实体在HTTP消息中都表示为字节序列,因此字节范围的概念对任何HTTP实体都有意义。(不过,并非所有客户端和服务器都需要支持字节范围操作。)
HTTP中的字节范围规范适用于实体主体中的字节序列(不一定与消息主体相同)。
字节范围操作可以指定单个范围的字节,或者指定单个实体中的一组范围。
ranges-specifier = byte-ranges-specifier
byte-ranges-specifier = bytes-unit “=” byte-range-set
byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
byte-range-spec = first-byte-pos “-” [last-byte-pos]
first-byte-pos = 1*DIGIT
last-byte-pos = 1*DIGIT
在byte-range-spec中给定的first-byte-pos值是第一个字节范围。last-byte-pos给定的是最后一个字节的范围。也就是说,指定的字节位置包括在内。字节的范围从0开始。
如果last-byte-pos存在,在byte-range-spec中必须大于或等于first-byte-pos,否则byte-range-spec规范在语法上是无效的。包含一个或多个语法无效的byte-range-spec值的byte-range-set的接收者必须忽略包含该byte-range-set的标头字段。
如果不存在last-byte-pos值,或者如果该值大于或等于实体主体的当前长度,则last-byte-pos的值被取为小于实体主体的当前长度的字节。
通过选择last-byte-pos,客户端可以在不知道实体大小的情况下限制检索的字节数。
suffix-byte-range-spec = “-” suffix-length
suffix-length = 1*DIGIT
suffix-byte-range-spec被用来用于指定实体主体的后缀,其长度由suffix-length值给出。(也就是说,该结构指定实体主体的最后N字节。)如果实体短于指定的suffix-length,则使用整个实体主体。
如果一个语法有效的byte-range-set包含至少一个byte-range-spec,其first-byte-pos小于实体主体的当前长度,或者至少一个非零的suffix-byte-range-spec,那么byte-range-set是可满足的。否则, byte-range-se是无法满足的。如果byte-range-set无法满足,服务器应该返回状态为416的响应(Requested range not satisfiable)。否则,服务器应该返回状态为206(Partial Content)的响应,其中包含实体主体的可满足范围。
下面是一个指定字节范围值的例子(假定实体主体的长度是10000):
– 最开始的500个字节 (字节范围是 0-499, 包含开始和结束的值): bytes=0-499
- 第二部分500个字节 (字节范围是 500-999, 包含开始和结束的值):bytes=500-999
- 最后500个字节 (字节范围是 9500-9999, 包含开始和结束的值):bytes=-500
- 或者 bytes=9500-
- 只有第一个和最后一个字节 (字节 0 和 9999): bytes=0-0,-1
– (字节范围 500-999, 包含开始和结束的值)下面是几个合法但不规范的第二部分字节的表示方法:
bytes=500-600,601-999
bytes=500-700,601-999
14.35.2 Range Retrieval Requests(范围检索请求)
使用条件或无条件GET方法的HTTP检索请求可以使用Range请求头请求实体的一个或多个子范围,而不是整个实体,它适用于作为请求结果返回的实体:
Range = “Range” “:” ranges-specifier
服务器可能忽略Range头字段。然而,HTTP/1.1源服务器和中间缓存应该尽可能支持字节范围,因为Range头字段支持对部分失败传输的高效恢复,并且支持对大型实体的高效部分检索。
如果服务器支持Range头字段,并且指定的范围适合实体:
- 无条件GET中出现的Range头字段会修改GET请求成功返回的内容。换句话说,响应的状态代码是206(Partial Content),而不是200 (OK)。
- 有条件的GET请求(使用If-Modifify-Since或者If-None-Match中一个或两个的请求,或者If-Unmodify-Since和If-Match中一个或两个的请求)中存在的Range头字段可以修改如果GET成功且条件为true时返回的内容。如果条件为false,则不影响返回的304(Not Modified)响应。
在某些情况下,除了Range头字段之外,使用If-Range头字段(参见14.27节)可能更合适。
如果支持范围的代理接收范围请求,将请求转发到入站服务器,并接收整个实体作为响应,那么它应该只将请求范围返回给客户端。如果响应与缓存分配策略一致,则应该将整个接收到的响应存储在缓存中。
14.36 Referer
Referer[sic]请求头字段允许客户端为服务器的着想的角度指定获取请求URI的资源的地址(“referrer”,尽管头字段拼错了)。Referer请求头允许服务器为感兴趣的资源生成返回链接列表,日志记录,优化缓存等等。它也允许对过时的或输入错误的链接进行跟踪以进行维护。如果从没有自己的URI(例如从用户键盘输入)的源获取请求URI,则不能发送Referer字段。
Referer = “Referer” “:” ( absoluteURI | relativeURI )
例子:
Referer: http://www.w3.org/hypertext/DataSources/Overview.html
如果字段值是一个相对URI,则应该将其解释为相对于请求URI。URI不能包含片段。有关安全方面的参考,请查看第15.1.3小节。
14.37 Retry-After
Retry-After 响应头字段可与503(Service Unavailable)响应一起使用,以指示请求客户端预期服务不可用的时间。此字段还可以与任何3xx(Redirection)响应一起使用,以指示用户代理在发出重定向请求之前等待的最短时间。该字段的值可以是HTTP-date值,也可以是响应时间之后的整数秒数(十进制)。
Retry-After = “Retry-After” “:” ( HTTP-date | delta-seconds )
下面是该字段用法的两个例子
Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
Retry-After: 120
第二个例子,需要延迟两分钟
14.38 Server
The Server response-header field contains information about the software used by the origin server to handle(操作,操控;) the request. The field can contain multiple product tokens (section3.8) and comments identifying(确认;辨认;认出) the server and any significant subproducts(子积;子乘积;[). The product tokens are listed in order of their significance(意义;重要性;意思) for identifying the application.
Server = “Server” “:” 1*( product | comment )
例子:
Server: CERN/3.0 libwww/2.17
If the response is being forwarded through a proxy, the proxy application MUST NOT modify the Server response-header. Instead, it SHOULD include a Via field (as described in section 14.45).
Note: Revealing(泄露;显示,展示;揭示,揭露) the specific software version of the server might allow the server machine to become more vulnerable(易受攻击的;易受伤的;易受批评的;[桥牌]已成局的) to attacks against software that is known to contain security holes. Server implementors(实现者) are encouraged(鼓动;鼓励) to make this field a configurable(结构的,可配置的) option.
14.39 TE
TE请求头字段指示它愿意在响应中接受哪些扩展传输编码,以及是否愿意接受分组传输编码中的trailer字段。它的值可能包括关键字“trailers”和(或)带有可选接收参数的以逗号分隔的扩展传递编码名称列表(如3.6节所述)。
TE = “TE” “:” #( t-codings )
t-codings = “trailers” | ( transfer-extension [ accept-params ] )
关键字“trailers”的出现表明客户愿意接受分段转换编码中的trailer字段,如 3.6.1节中定义的那样。这个关键字保留用于传输编码值,即使它本身并不表示传输编码。
它的用法:
TE: deflate
TE:
TE: trailers, deflate;q=0.5
TE头字段仅适用于短连接(immediate connection)。因此,当HTTP/1.1消息中出现TE时,必须在连接标头字段(14.10小节)中提供关键字。
根据TE字段,服务器使用以下规则测试传输编码是否可接受:
1. “chunked”的转换编码总是可以接受的。如果列出了关键字“trailers”,则客户端表示它愿意代表自己和任何下游客户接受chunked响应中的trailer字段。这意味着,如果给定,客户端将声明,要么所有下游客户端都愿意接受转发响应中的trailers字段,要么它将尝试代表下游接收者缓冲响应。
注意:HTTP/1.1没有定义任何方法来限制chunked响应的大小,从而确保客户端能够缓冲整个响应。
2.如果正在测试的传输编码是TE字段中列出的传输编码之一,那么它是可以接受的,除非qvalue的值为0。(在3.9节中定义,0的qvalue值表示“不可接受”。)
3. 如果多个传输编码是可接受的,则首选具有最高非零qvalue值的可接受传输编码。“chunked”转换编码的qvalue值总是为1。
如果TE字段值为空或不存在TE字段,则唯一的传输编码是“chunked”。没有传输编码的消息总是可以接受的。
14.40 Trailer
Trailer通用头字段值用来表示给定的头字段集存在于用分块“传输编码”编码的消息的trailer中。
Trailer = “Trailer” “:” 1#field-name
HTTP/1.1消息应该包含消息中的Trailer头字段,该字段使用非空Trailer的分组传输编码。这样做可以让接收者知道Trailer中期望的是哪个头字段。
If no Trailer header field is present, the trailer SHOULD NOT include any header fields. See section 3.6.1 for restrictions on the use of trailer fields in a “chunked” transfer-coding.
如果不存在Trailer头字段,那么trailer不应该包含任何头字段。请参阅第3.6.1节,了解在“chunked”传输编码中使用trailer字段的限制。
在Trailer头字段中列出的消息头字段不能包含以下头字段:
. Transfer-Encoding
. Content-Length
. Trailer
14.41 Transfer-Encoding
Transfer-Encoding 通用头字段指示向消息体应用了什么(如果有的话)类型的转换,以便在发送方和接收方之间安全地传输它。这与内容编码不同,因为传输编码是消息的属性,而不是实体的属性。
Transfer-Encoding = “Transfer-Encoding” “:” 1#transfer-coding
Transfer-codings在 3.6小节中有详细的定义。下面是一个例子:
Transfer-Encoding: chunked
如果多个编码被应用到一个实体,那么传输编码必须按照应用它们的顺序列出。有关编码参数的其他信息可以由本规范未定义的其他实体头字段提供。
大多数应用HTTP/1.0的协议无法理解Transfer-Encoding头字段。
14.42 Upgrade
Upgrade通用头字段允许客户端指定它支持哪些附加通信协议,如果服务器发现它适合交换协议,则允许客户端使用哪些附加通信协议。服务器必须在101(Switching Protocols)响应中使用Upgrade头字段来指示正在交换哪些协议。
Upgrade = “Upgrade” “:” 1#product
例如,
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
Upgrade头字段旨在提供一个简单的机制,用于从HTTP/1.1转换到其他不兼容的协议。它通过允许客户端声明它想要使用另一种协议来实现这一点,比如使用更高主版本号的HTTP的后期版本,即使当前的请求是使用HTTP/1.1发出的。这通过允许客户端在更普遍支持的协议中发起请求,同时向服务器指示如果可用,它希望使用“更好”的协议(“更好”由服务器决定,可能根据所请求的方法和/或资源的性质不同而不同。),从而减轻了不兼容协议之间转换困难的问题。
Upgrade头字段仅适用于现有传输层连接上的交换应用层协议。Upgrade不能用于坚持更改协议;服务器的接受和使用是可选的。协议改变后的应用层通信的能力和性质完全取决于所选择的新协议,尽管改变协议之后的第一动作必须是对包含Upgrade头字段的初始HTTP请求的响应。
Upgrade头字段仅适用于立即连接。因此,每当在HTTP/1.1消息中存在Upgrade时,必须在Connection头字段(部分14.10)中提供upgrade关键字。
Upgrade头字段不能用于指示在不同连接上切换协议。为此,使用301, 302, 303或305等重定向响应更合适。
本规范只定义了供超文本传输协议族使用的协议名称“HTTP”,如3.1节的HTTP版本规则和本规范的未来更新所定义。任何令牌都可以用作协议名称;但是,只有当客户端和服务器都把该名称与相同的协议关联时才有用。
14.43 User-Agent
User-Agent请求头字段包含关于发起请求的用户代理的信息。这是为了统计请求的意图、跟踪违反协议的情况以及自动识别用户代理,以便调整响应以避免特定的用户代理限制。用户代理应该将此字段包含在请求中。字段可以包含多个产品标记(第3.8节)和标识代理和构成用户代理重要部分的任何子产品的注释。按照惯例,产品令牌是按照它们对识别应用程序的重要性列出的。
User-Agent = “User-Agent” “:” 1*( product | comment )
例子:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
14.44 Vary
Vary字段值表示请求头字段集,该字段集在响应是“新鲜”的情况下完全确定是否允许缓存使用响应来响应后续请求,而无需重新验证。对于无法缓存或过时的响应,Vary字段值向用户代理提供用于选择表示的标准。值“*”表示缓存无法从后续请求的请求头中确定此响应是否合适。请参阅第 13.6节,了解缓存对Vary头字段的使用。
Vary = “Vary” “:” ( “*” | 1#field-name )
HTTP/1.1服务器应该包含一个Vary头字段,其中包含任何可缓存的响应,该响应受服务器驱动协商的影响。这样做允许缓存正确地解释对该资源的未来请求,并告知用户代理该资源上是否存在协商。服务器可能包含一个Vary标头字段,其中不可缓存的响应受服务器驱动协商的影响,因为这可能为用户代理提供关于“响应”在响应时变化的维度的有用信息。
一个Vary字段值,由一组字段名称信号组成,所选的响应表示是基于选择算法的,该算法在选择最合适的表示时只考虑列出的请求头字段。缓存可能假设在响应新鲜的时间段内,对于将来具有相同值的请求,将进行相同的选择。
给出的字段名不限于此规范定义的标准请求头字段集。且字段名不区分大小写。
如果Vary的字段值是“*”,则表明未指定的参数不限于请求头(例如,客户端的网络地址),在响应表示的选择中起作用。“*”值不能由代理服务器生成;它可能仅由原始服务器生成。
14.45 Via
Via通用头字段必须被网关和代理使用,以用来在请求中指示用户代理和服务器之间的中间协议和接收者,在响应上指示源服务器和客户端之间的中间协议和接收者。它类似于RFC 822[9]的“Received”字段,用于跟踪消息转发,避免请求循环,以及识别请求/响应链上所有发送者的协议功能。
Via = “Via” “:” 1#( received-protocol received-by [ comment ] )
received-protocol = [ protocol-name “/” ] protocol-version
protocol-name = token
protocol-version = token
received-by = ( host [ “:” port ] ) | pseudonym
pseudonym = token
接收协议指示服务器或客户端沿着请求/响应链的每个环节所接收的消息相关的协议版本。当消息被转发时,接收的协议版本被附加到Via字段的值上,以便关于上游应用程序的协议能力的信息对所有接收者保持可见。
协议名称是可选的,当且仅当它是“HTTP”时。接收方字段通常是随后转发消息的接收方服务器或客户端的主机和可选端口号。然而,如果真实主机被认为是敏感信息,它可以被化名取代。如果没有给出端口,则可以假定它是接收到的协议的默认端口。
多个Via字段值表示转发消息的每个代理或网关。每个接收方必须附加其信息,以便根据转发应用程序的序列对最终结果进行排序。
注释可以在Via头字段中使用,以标识接收方代理或网关的软件,类似于User-Agent和Server标头字段。但是,在传递字段中的所有注释都是可选的,并且可以在转发消息之前由任何接收者删除。
例如,可以将请求消息从HTTP/1.0用户代理发送到名为“fred”的内部代理,该代理使用HTTP/1.1将请求转发到nowhere.com的公共代理,该公共代理通过将请求转发到位于www.ics.uci.edu的源服务器来完成请求。由www.ics.uci.edu接收的请求将具有以下的Via头字段:
Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
默认情况下,代理和网关作为通过网络防火墙的门户不应该转发防火墙区域内的主机的名称和端口。只有显式启用该信息才能传播。如果没有启用,防火墙后面的任何主机的主机所接收的主机都应该用适当的化名替换。
对于对隐藏内部结构具有很强隐私要求的组织,代理可以将具有相同接收协议值的Via头字段条目的有序子序列组合到一个这样的条目中。例如,
Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
可以缩减为
Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
应用程序不应该组合多个条目,除非它们都在相同的组织控制之下,并且主机已经被假名取代。应用程序不能组合具有不同接收的协议值的条目。
14.46 Warning
Warning通用头字段用于承载关于消息中可能未反映的消息的状态或转换的附加信息。此信息用于警告实体主体信息在缓存配置或转换中缺乏语义的透明度。
Warning头字段通过以下方式发送:
Warning = “Warning” “:” 1#warning-value
warning-value = warn-code SP warn-agent SP warn-text
[SP warn-date]
warn-code = 3DIGIT
warn-agent = ( host [ “:” port ] ) | pseudonym
; 服务器添加的名称或别名
; Warning头字段,用于调试
warn-text = quoted-string
warn-date = <“> HTTP-date <“>
响应可能包含多个Warning头字段。
警告文本应该使用自然语言和字符集,对于接收响应的人类用户来说,这些语言和字符集最容易理解。此决策可以基于任何可用的知识,例如缓存或用户的位置、请求中的Accept-Language字段、响应中的Content-Language字段等。默认语言为英语,默认字符集为ISO-8859-1。
如果使用的字符集不是ISO-859-1,则必须使用RFC 2047(14)中描述的方法在警告文本中进行编码。
Warning头通常可以应用于任何消息,但是一些特定的警告代码对于缓存来说是特殊的,并且只能应用于响应消息。在任何现有的Warning标头之后都应该添加新的警告标题。缓存不能删除它收到的任何消息头。但是,如果缓存成功验证缓存条目,则应删除以前附加到该条目的任何Warning标头,除非为特定Warning代码指定。然后,必须在验证响应中添加任何Warning标头。换句话说,Warning标头是那些附加到最近的相关响应的标题。
当多个Warning头附加到响应时,用户代理应该尽可能多地通知用户,以使它们出现在响应中。如果无法将所有警告通知用户,用户代理应遵循以下启发式方法:
– 出现在响应中较早的警告优先于出现在响应中较晚的警告。
- 用户首选字符集中的警告优先于其他字符集中的警告,但是警告代码和警告代理是相同的。
生成多个Warning标头的系统应该根据用户代理行为对其进行排序。
有关警告的缓存行为的需求在第13.1.2节中说明。
这是当前定义的警告代码的列表,每个警告代码都带有英文推荐的警告文本,并描述了其含义。
110 – 当响应过期时,则必须被包含。
111 – 如果由于无法连接到服务器而引起的重校验失败导致了缓存返回了一个陈旧的响应,则“重新校验失败”必须被包含。
112 – 如果缓存有意从网络的其余部分断开一段时间,则应该包含“断开连接操作”。
113 – 如果缓存从启发意义上选择的新鲜度范围大于24小时,响应的范围大于24小时。则“探索性过期”必须被包含。
199 – 杂项警告,警告文本可以包括要呈现给人类用户或登录的任意信息。接受此警告的系统除了向用户发出警告外,不得采取任何自动化行动。
214 – 应用转换必须由中间缓存或代理添加,如果它应用任何转换来更改响应的内容编码(如Content-Encoding标头中指定的)或媒体类型(如Content-Type标头中指定的)或响应的实体主体,除非该Warning字段已经出现在响应中。
299 – 杂项持久警告,警告文本可以包括要呈现给人类用户或登录的任意信息。接收此警告的系统不能采取任何自动化操作。
如果实现发送的消息具有一个或多个警告标头,其版本为HTTP/1.0或更低,那么发送方必须在每个警告值中包含一个与响应中的日期匹配的警告日期。
如果一个实现接收到包含警告日期的警告值的消息,并且该警告日期与响应中的日期值不同,那么在存储、转发或使用消息之前,该警告值必须从消息中删除。(这可以防止警告标头字段初始缓存的不良后果。)如果出于这个原因删除了所有警告值,那么警告头也必须被删除。
14.47 WWW-Authenticate
WWW-Authenticate响应头字段必须包含在401(Unauthorized)响应消息中。字段值由至少一个询问组成,该询问指示身份验证方案和适用于Request-URI的参数。
WWW-Authenticate = “WWW-Authenticate” “:” 1#challenge
HTTP访问身份验证过程描述为“HTTP身份验证:基本和摘要访问身份验证”[43]。建议用户代理在解析WWW-Authenticate字段值时特别小心,因为它可能包含多个质询,或者如果提供了多个WWW-Authenticate头字段,则质询本身的内容可以包含一个逗号分隔的身份验证参数列表。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/124403.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...