超文本传输协议-HTTP/1.1(修订版)

超文本传输协议-HTTP/1.1(修订版)
---译者:孙超进
---email:sunchaojin@163.com
说明
本文档规定了互联网社区的标准组协议,并须要讨论和建议以便更加完善。请参考
“互联网官方协议标准”(STD 1)来了解本协议的标准化状态。本协议不限流传发布。
版权声明
Copyright (C) The Internet Society (1999). All Rights Reserved.
摘要
超文本传输协议(HTTP)是一种为分布式,协做式的,超媒体信息系统。它是一种通用的,无
状态(stateless)的协议,除了应用于超文本传输外,它也能够应用于诸如名称服务器和分布
对象管理系统之类的系统,这能够经过扩展它的请求方法,错误代码和消息头[47]来实现。
HTTP的一个特性就是是数据表现形式是能够定义的和可协商性的,这就容许系统能独立于于
数据传输被构建。
HTTP 在1990 年WWW 全球信息刚刚起步的时候就获得了应用。本说明书详细阐述了
HTTP/1.1 协议,是RFC 2068的修订版[33]。
目录(略)
1 引论
1.1 目的
超文本传输协议(HTTP)是一种为分布式的,协做的,超媒体信息系统,它是面向应用层的
协议。在1990年WWW全球信息刚刚起步的时候HTTP就获得了应用。HTTP的第一个版本叫作
HTTP/0.9,是一种为互联网原始数据传输服务的简单协议。由RFC 1945[6]定义的HTTP/1.0进一
步完善了这个协议。它容许消息以类MIME消息的格式传送,它包括传输数据的元信息和对请
求/响应语义的修饰。可是,HTTP/1.0没有充分考虑到分层代理,缓存的,以及持久链接和虚拟
主机的需求的影响。而且随着不完善的HTTP/1.0应用程序的激增,这就迫切须要一个新的版本,
以便能使两个通讯程序可以肯定彼此的真实能力。
此规范定义的协议叫作“HTTP/1.1”,.这个协议与HTTP/1.0相比,此规范更为严格,以确保
各个协议的特征获得可靠实现。
实际的信息系统除了简单的获取信息以外,还要求更多的功能,包括查找(search),终端更
新(front-end update)和注解(annotation)。HTTP为请求提供可扩充方法集和消息头集
[47]。HTTP是创建在统一资源标识符(URI)[3]的约束上的,做为一个地址(URL)[4]或名称
(URN)[20],以指定被一个方法使用的资源。消息以一种相似于互联网邮件[9]消息格式来传
输的,互联网消息格式定义于多目的互联网邮件扩展(MIME)[7]里。
HTTP也是用于用户代理(user agents)和其它互联网系统的代理/网关之间通讯的通讯协议,
这些互联网系统可能由SMTP[16],NNTP[13],FTP[18],Gopher[2]和WAIS[10]协议支持。经过
这种方式,HTTP容许不一样的应用程序对资源进行基本的超媒体访问。
1.2 要求
本文的关键词“必须”( "MUST"),,“不能”("MUST NOT"),“须要”(
"REQUIRED"), “应该”("SHALL"),“不该该”("SHALL NOT"),“应该”
( "SHOULD" ) , “ 不该该” ( "SHOULD NOT" ) , “ 建议的” (
"RECOMMENDED"),“可能”("MAY"), 和“可选的”( "OPTIONAL")将由RFC
2119[34]解释。
一个应用程序若是不能知足协议提供的一个或多个MUST或REQUIRED等级的要求,是不符
合要求的。一个应用程序若是知足全部必须(MUST)或须要的(REQUIRED)等级以及全部
应该(SHOULD)等级的要求,则被称为非条件遵循(unconditionally compliant)的;若满
足全部必须(MUST)等级的要求但不能知足全部应该(SHOULD)等级的要求则被称为条件
遵循的(conditionally compliant)。
1.3 术语
本说明用到了若干术语,以表示HTTP通讯中各参与者和对象扮演的不一样角色。
链接(connection)
为通讯而在两个程序间创建的传输层虚拟电路。
消息(message)
HTTP通讯中的基本单元。它由一个结构化的八比特字节序列组成,与第4章定义的句法相匹
配,并经过链接获得传送。
请求(request)
一种HTTP请求消息,参看第5章的定义。
响应(response)
一种HTTP响应消息,参看第6章的定义。
资源(resource)
一种网络数据对象或服务,能够用第3.2节定义的URI指定。资源能够以多种表现方式(例如
多种语言,数据格式,大小和分辨率)或者根据其它方面而而不一样的表现形式。
实体(entity)
实体是请求或响应的有效承载信息。一个实体包含元信息和内容,元信息以实体头域(entityheader
field)形式表示,内容以消息主体(entity-body)形式表示。在第7章详述。
表现形式 (representation)
一个响应包含的实体是由内容协商(content negotiation)决定的。如第12章所述。有可能存在
一个特定的响应状态码对应多个表现形式。
内容协商(content negotiation)
当服务一个请求时选择资源的一种适当的表示形式的机制(mechanism),如第12节所述。任
何响应里实体的表现形式都是可协商的(包括错误响应)。
变量(variant)
在某个时刻,一个资源对应的表现形式(representation)能够有一个或多个(译注:一个
URI请求一个资源,但返回的是此资源对应的表现形式,这根据内容协商决定)。每一个表现形
式(representation)被称做一个变量。 ‘变量’这个术语的使用并不意味着资源
(resource)是由内容协商决定的.。
客户端(client)
为发送请求创建链接的程序.。
用户代理(user agent)
初始化请求的客户端程序。常见的如浏览器,编辑器,蜘蛛(可网络穿越的机器人),或其余
的终端用户工具.
服务器(Server)
服务器是这样一个应用程序,它赞成请求端的链接,并发送响应(response)。任何给定的程
序都有可能既作客户端又作服务器;咱们使用这些术语是为了说明特定链接中应用程序所担当
的角色,而不是指一般意义上应用程序的能力。一样,任何服务器均可以基于每一个请求的性质
扮演源服务器,代理,网关,或者隧道等角色之一。
源服务器(Origin server)
存在资源或者资源在其上被建立的服务器(server)被成为源服务器(origin server)。
代理( Proxy)
代理是一个中间程序,它既能够担当客户端的角色也能够担当服务器的角色。代理表明客户端
向服务器发送请求。客户端的请求通过代理,会在代理内部获得服务或者通过必定的转换转至
其余服务器。一个代理必须能同时实现本规范中对客户端和服务器所做的要求。透明代理
(transparent proxy)须要代理认证和代理识别,而不修改请求或响应。非透明代理(nontransparent
proxy)需修改请求或响应,以便为用户代理(user agent)提供附加服务,附加
服务包括组注释服务,媒体类型转换,协议简化,或者匿名过滤等。除非透明行为或非透明行
为经被显式地声明,不然,HTTP代理既是透明代理也是非透明代理。
网关(gateway)
网关实际上是一个服务器,扮演着表明其它服务器为客户端提供服务的中间者。与代理(proxy)
不一样,网关接收请求,仿佛它就是请求资源的源服务器。请求的客户端可能觉察不到它正在同
网关通讯。
隧道(tunnel)
隧道也是一个中间程序,它一个在两个链接之间充当盲目中继(blind relay)的中间程序。一旦
隧道处于活动状态,它不能被认为是此次HTTP通讯的参与者,虽然HTTP请求可能已经把它
初始化了。当两端的中继链接都关闭的时候,隧道再也不存在。
缓存(cache)
缓存是程序响应消息的本地存储。缓存是一个子系统,控制消息的存储、获取和删除。缓存里存
放可缓存的响应(cacheable response)为的是减小对未来一样请求的响应时间和网络带宽消
耗。任一客户端或服务器均可能含有缓存,但缓存不能存在于一个充当隧道(tunnel)的服务器
里。
可缓存的(cacheable)
咱们说响应(response)是可缓存的,若是这个响应能够被缓存(cache)保存其副本,为的
是能响应后续请求。肯定HTTP响应的缓存能力(cacheability)在13节中有介绍。即便一个资
源(resourse)是可缓存的,也可能存在缓存是否能利用此缓存副本为某个特定请求的约束。
第一手的(first-hand)
若是一个响应直接从源服务器或通过若干代理(proxy),而且没有没必要要的延时,最后到达
客户端,那么这个响应就是第一手的(first-hand)。
若是响应经过源服务器(origin server)验证是有效性(validity)的,那么这个响应也一样是
第一手的。
显式过时时间(explicit expiration time)
是源服务器认为实体(entity)在没有被进一步验证(validation)的状况下,缓存(cache)
不该该利用其去响应后续请求的时间(译注:也就是说,当响应的显式过时时间达到后,缓存
必需要对其缓存的副本进行重验证,不然就不能去利用此副本去响应后续请求)。
启发式过时时间(heuristic expiration time)
当没有显式过时时间(explicit expiration time)可利用时,由缓存指定过时时间.
年龄(age)
一个响应的年龄是从被源服务器发送或被源服务器成功验证到如今的时间。
保鲜寿命(freshness lifetime)
一个响应产生到过时之间的时间。
保鲜(Fresh)
若是一个响应的年龄尚未超过保鲜寿命(freshness lifetime),那么它就是保鲜的.。
陈旧(Stale)
一个响应的年龄已经超过了它的保鲜寿命(freshness lifetime),那么就是陈旧的.
语义透明(semantically transparent)
缓存(cache)可能会以一种语意透明(semantically transparent)的方式工做。这时,对于
一个特定的响应,使用缓存既不会对请求客户端产生影响也不会对源服务器产生影响,缓存的
使用只是为了提升性能。当缓存(cache)具备语意透明时,客户端从缓存接收的响应跟直接从
源服务器接收的响应彻底一致(除了使用hop-by-hop头域)。
验证器(Validator)
验证器实际上是协议元素(例如:实体标签(entity tag)或最后修改时间(last-modified time)
等),这些协议元素被用于识别缓存里保存的副本(即缓存项)是否等价于源服务器的实体的
副本。
上游/下游(upstream/downstream)
上游和下游描述了消息的流动:全部消息都是从上游流到下游。
内向/外向(inbound/outbound)
内向和外向指的是消息的请求和响应路径:“内向”即“移向源服务器”,“外向”即“移向
用户代理(user agent)”。
1.4 整体操做
HTTP 协议是一种请求/响应型的协议。 客户端给服务器发送请求的格式是一个请求方法
(request method),URI,协议版本号,而后紧接着一个包含请求修饰符(modifiers),客
户端信息,和可能的消息主体的类MIME(MIME-like)消息。服务器对请求端发送响应的格式
是以一个状态行(status line),其后跟随一个包含服务器信息、实体元信息和可能的实体主体
内容的类MIME(MIME-like)的消息。其中状态行(status line)包含消息的协议版本号和一
个成功或错误码。HTTP和MIME之间的关系如附录19.4节所阐述。
大部分的HTTP通讯是由用户代理(user agent)发起的,由应用于一个源服务器资源的请求
构成。最简单的情形,这能够经过用户代理(UA)和源服务器(O)之间的单一链接(v)来实
现。
请求链(Request chain)-------------------------------------- ----------
用户代理(UA)----------------单一链接(v)--------------源服务器(O)
<----------------------------------------------------------响应链(response chain)
有可能在请求/响应链中出现一个或多个中间者(intermediares),这是比较复杂的情形。常见
的中间者(intermediares)有三种:代理(proxy),网关(gateway)和隧道(tunnel)。代
理(proxy)是一种转发代理(a forwarding agent),它接收绝对URI(absoulute url,相对
于相对url)请求,重写所有或部分消息,而后把格式化后的请求发送到URI指定的服务器上。
网关是一种接收代理(receiving agent),它充当一个在服务器之上的层(layer),必要时它
会把请求翻译成为下层服务器的协议。隧道不改变消息而充当两个链接之间的中继点;它用于
通讯须要穿过中间者(如防火墙)甚至当中间者不能理解消息内容的时候。
请求链(request chain)----------------------------------------
UA-----v-----A-----v-----B-----v-----C------------v-----------------O
<----------------------------------------响应链(response chain)
上图显示了用户代理(user agent)和源服务器之间的三个中间者(A,B和C)。整条链的请
求或响应将会经过四个被隔离开的链接。这个不一样点很重要,由于某些HTTP通讯选项有可能
只能采用最近的非隧道邻接点的链接,有可能只采用链的端点(end-point),或者也有可能只
采用于链上全部链接。图表尽管是线性的,每一个参与者可能忙于多个并发的通讯。例如,B能够
接收来自不是A的许多客户端的请求,而且/或者能够把请求转发到不是C的服务器,与此同
时C正在处理A的请求。
通讯中任何非隧道成员均可能会采用一个内部缓存(internal cache)来处理请求。若是沿着链
的成员有请求已缓存的响应,请求/响应链就会大大缩短。下图阐明了一个最终请求响应链,假
定B拥有一个来自于O(经过C)的之前请求响应的缓存副本,而且此请求的响应并未被UA
或A缓存。
请求链(request chain)---------->
UA-----v----------A-----v-----B-----C----O
<---------响应链 (response chain)
并非全部的响应都能有效地缓存,一些请求可能含有修饰符(modifiers),这些修饰符对缓
存动做有特殊的要求。HTTP对缓存行为(behavior)和可缓存响应(cacheable responses)
的定义在第13章定义。
实际上,目前万维网上有多种被实践和部署的缓存和代理的体系结构和配置。这些系统包括节
省带宽的缓存代理(proxy cache)层次(hierarchies)系统,能够广播(broadcast)或多播
(multicast)缓存数据的系统,经过CD-ROM发布缓存数据子集的机构,等等。HTTP系统
(http system)会被应用于宽带链接的企业局域网中的协做,而且能够被用于PDAs进行低耗
无线断续链接访问。HTTP1.1的宗旨是为了支持各类各样的已经部署的配置,同时引进一种协
议结构,让它知足能够创建高可靠性的web应用程序,即便不能达到这种要求,也至少能够可
靠的定位故障。
HTTP通讯一般发生在TCP/IP链接上。默认端口是TCP 80,不过其它端口也能够使用。但并不
排除HTTP协议会在其它协议之上被实现。HTTP仅仅指望的是一个可靠的传输(译注:HTTP
通常创建在传输层协议之上);因此任何提供这种保证的协议均可以被使用;协议传输数据单
元(transport data unit)与HTTP/1.1请求和响应的消息结构之间的映象已经超出了本规范的
范围。
大部分HTTP/1.0 的实现都是对每一个请求/响应交换(exchange)产生一个新的链接。而
HTTP/1.1中,一个链接能够用于一个或更多请求/响应交换,虽然链接可能会由于各类缘由中
断(见第8.1节)。
2 符号习惯和通常语法
2.1 扩充的BNF(扩充的 巴科斯-诺尔范式)
本文档规定的全部机制都用两种方法描述:散文体(prose)和相似于RFC 822 的扩充
Backus-Naur Form(BNF)。要理解本规范,使用者需熟悉符号表示法。扩充BNF结构以下:
名字(name)=定义(definition)
名字(name)就是表明规则的名字,规则名里不能包含“<”和“>”,经过等号把规则名和规
则定义(definiation)分离开。空格只有在采用延续行缩进来指定跨度多于一行的规则定义的时
候才有意义。某些基本规则(basic rules)使用大写字母包含在规则定义里, 如
SP,LWS,HT,CRLF,DIGIT,ALPHA,等等。尖括号能够包含在规则定义里,只要它们的
存在有利于区分规则名的使用。
“字面文本”(“literal”)
字面文本(literal text)两边用引号。除非声明,字面文本大小写不敏感(译注:如,HEX =
"A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT 里的A,B,C,D等等都是字
面文本(literal text))。
规则1 | 规则2
由竖线(“|”)分开的元素是可选的,例如,“yes | no”表示yes或no都是可接受的。
(规则1 规则2)
围在括号里的多个元素视做一个元素。因此,“(elem (foo | bar) elem)”符合的字符串是“elem
foo elem”和“elem bar elem”。
*规则
前面的字符“*”表示重复。完整的形式是“<n>*<m>元素”,表示元素至少出现<n>次,至多出
现<m>次。默认值是0和无穷大,因此"*(元素)"容许任何数值,包括零;"1*元素"至少出现一
次;"1*2element"容许出现一次或两次。
[规则]
方括号里是任选元素;“[foo bar]”至关于“*1(foo bar)”。
N 规则
特殊的重复:“<n>(元素)”与“<n>*<n>(元素)”等价;就是说,(元素)正好出现
<n>次。这样2DIGIT是一个两位数字,3ALPHA是一个由三个字符组成的字符串。
#规则
相似于“*”,结构“#”是用来定义一系列元素的。完整的形式是<n>#<m>元素,表示至少<n>个
元素,至多<m>个元素,元素之间被一个或多个逗号(“,”)以及可选的线性空白(LWS)隔
开了。这就使得表示列表这样的形式变得很是容易;像
(*LWS element *(*LWS ","*LWS element))
就能够表示为
1#element
不管在哪里使用这个结构,空元素都是容许的,可是不计入元素出现的次数。换句话说 ,
“(element ), , (element) ”是容许的,可是仅仅视为两个元素。所以,在至少须要一个
元素的地方,必须存在至少一个非空元素。默认值是0和无穷大,这样,“#element”容许任意
零个或多个元素;“1# element”须要至少一个;“1#2element”容许一个或两个元素。
注释(comment)
用分号引导注释。
隐含的*LWS
本规范所描述的语法是基于字(word-based)的。除非特别注明,线性空白(LWS)能够出现
在任何两个相邻字之间(标记(token)或引用字符串(quoted-string)),以及相邻字和间
隔符之间,可是这并无改变对一个域的解释。任何两个标记(token)之间必须有至少一个分
割符,不然将会被理解为只是一个标记。
2.2基本规则 (basic rule)
下面的规则贯穿于本规范的全文,此规则描述了基本的解析结构。US-ASCII(美国信息交换标
准码)编码字符集是由ANSI X3.4-1986[21]定义的。
OCTET(字节) = <任意八比特的数据序列>
CHAR = <任意ASCII字符(ascii码值从 0到127的字节)>
UPALPHA = <任意大写字母"A"..."Z">
LOALPHA = <任意小写字母"a"..."z">
ALPHA = UPALPHA | LOALPHA
DIGIT = <任意数字0,1,...9>
CTL = <任意控制字符(ascii码值从0 到 31的字节)及删除键DEL(127>
CR = <US-ASCII CR, 回车(13)>
LF = <US-ASCII LF, 换行符(10)>
SP = <US-ASCII SP, 空格(32)>
HT = <US-ASCII HT, 水平制表 (9)>
<"> = <US-ASCII双引号(34)>
HTTP/1.1 将 CR LF 的序列定义为任何协议元素的行尾标志,但这个规定对实体主体
(endtity-body)除外(要求比较松的应用见附录19.3)。实体主体(entity-body)的行尾标志
是由其相应的媒体类型定义的,如3.7节所述。
CRLF = CR LF
HTTP/1.1 的消息头域值能够折叠成多行,但紧接着的被折叠行由空格(SP)或水平制表
(HT)折叠标记开始。全部的线性空白(LWS)包括被折叠行的折叠标记(空格SP或水平制
表键HT),具备同SP同样的语义。接收者在解析域值而且将消息转送到下游(downstream)
以前可能会将任何线性空白(LWS)替换成单个SP(空格)。
LWS = [CRLF] 1*(SP | HT)
下面的TEXT规则仅仅适用于头域内容和值的描述,不会被消息解释器解析。TEXT里的字能够
包含不只仅是ISO-8859-1[22]里的字符集,也能够包含RFC 2047里规定的字符集。
TEXT = <除CTLs之外的任意OCTET,但包括LWS>
一个CRLF只有做为HTTP消息头域延续的一部分时才在TEXT定义里使用。
十六进制数字字符用在多个协议元素(protocol element)里。
HEX = "A" | "B" | "C" | "D" | "E" | "F"
| "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
许多HTTP/1.1的消息头域值是由LWS或特殊字符分隔的字构成的。这些特殊字符必须先被包
含在引用字符串(quoted string)里以后才能用于参数值(如3.6节定义)里。
token (标记) = 1*<除CTLs与分割符之外的任意CHAR >
separators(分割符) = "(" | ")" | "<" | ">" | "@"
| "," | ";" | ":" | "\" | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
经过用圆括号括起来,注释(comment)能够包含在一些HTTP头域里。注释只能被包含在域
值定义里有“comment”的域里。在其余域里,圆括号被视做域值的一部分。
comment (注释)= "(" *(ctext | quoted-pair | comment )” )"
ctext = <除"(" 和 ")"之外的任意TEXT >
若是一个TEXT若被包含在双引号里,则看成一个字。
quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
qdtext = <any TEXT except <">>
斜划线("\")能够被做为单字符的引用机制,可是必需要在quoted-string和comment构造之
内。
quoted-pair = "\" CHAR
3 协议参数
3.1 HTTP版本
HTTP使用一个“<major>.<minor>”数字模式来指明协议的版本号。为了进一步的理解HTTP
通讯,协议的版本号指示了发送端指明消息的格式和能力,而不只仅是经过双方通讯而得到的
通讯特性。当消息元素的增长不会影响通讯行为或扩展了域值时,协议版本是不须要修改的。当
协议会由于添加一些特征而作了修改时,<minor>数字就会递增。这些修改不会影响一般的消息
解析算法,但它会给消息添加额外的语意(semantic)而且会暗示发送者具备额外的能力。协
议的消息格式发生变化时,<major>数字就会增长。
HTTP消息的版本在HTTP-Version域被指明,HTTP-Version域在消息的第一行中。
HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
注意major和minor数字必须被当作两个独立整数,每一个整数均可以递增,而且能够增大到大
于一位数的整数,如HTTP/2.4比HTTP/2.13低,而HTTP/2.4又比HTTP/12.3低。前导0必
须被接收者忽略而且不能被发送者发送。
一个应用程序若是发送或响应消息里的包含HTTP-Version为“HTTP/1.1”的消息,那么此应
用程序必须至少条件遵循此协议规范。最少条件遵循此规范的应用程序应该把“HTTP/1.1”包含
在他们的消息的HTTP-Version里,而且对任何不兼容HTTP/1.0的消息也必须这么作。关于何
时发送特定的HTTP-Version值的细节,参见RFC2145[36]。
应用程序的HTTP版本是应用程序最少条件遵循的最高HTTP版本。
当代理或网关应用程序转发(forwarding)消息的协议版本不一样于代理或网关应用程序自己协
议版本的时候,代理(proxy)和网关(gateway)应用程序就要当心。由于消息里协议版本说
明了发送者处理协议的能力,因此一个代理/网关千万不要发送一个高于该代理/网关应用程序
协议版本的消息。若是代理或网关接收了一个更高版本的消息,它必需要么使协议的版本下降,
要么以一个错误响应,或者要么切换到隧道行为(tunnel behavior)。
自从RFC 2068[33]发布后,因为存在与HTTP/1.0代理(proxy)的互操做问题,因此缓存代
理(caching proxies)必须能提高请求的版本到他们能支持的程度,但网关(gateway)能够
这么作也能够不这么作,而隧道(tunnels)却不能这么作。代理(Proxy)/网关(gateway)
的响应(Response)必须和请求(request)的主版本(major version)号保持一致。
注意:HTTP版本间的转换可能会对消息头域(header fields)在版本里有或没有而进行改变。
3.2 通用资源标识符(URI)
URIs有许多名字已为人所知:WWW地址,通用文档标识符,通用资源标识符[3],以及后来
的统一资源定位器(URL)[4]和统一资源名称(URN)[20]。就HTTP而言,通用资源标识符
(URI)只是简单的格式化字符串---经过名称,位置,或其它特征---识别一个资源。
3.2.1 通常语法
根据使用的背景,HTTP里的URIs能够表示成绝对(absoulute)形式或相对形式(相对URI
基于根URI[11])。两种形式的区别是根据这样的事实:绝对URI老是以一个模式(scheme)
名做为开头,其后是一个冒号。关于URL 更详尽的语法和含义请参看“统一资源标识符
(URI):通常语法和语义”,RFC 2396 [42](代替了RFCs 1738 [4]和RFC 1808 [11])。本
规范采用了RFC 2396 里的” URIreference”
, "absoluteURI" , "relativeURI" , "port" , "host" , "abs_path" , "rel_path",
和"authority"的定义格式。
HTTP协议不对URI的长度做事先的限制,服务器必须可以处理任何他们提供资源的URI,并
且应该可以处理无限长度的URIs,这种无效长度的URL可能会在客户端以基于GET方式的
请求时产生。若是服务器不能处理太长的URI的时候,服务器应该返回414状态码(此状态码
表明Request-URI太长)。
注:服务器在依赖大于255字节的URI时应谨慎,由于一些旧的客户或代理实现可能不支持这
些长度。
3.2.2 HTTP URL
在HTTP协议里,http模式(http scheme)被用于定位网络资源(resourse)的位置。本节定
义了http URLs这种特定模式(scheme)的语法和语义。
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
若是端口为空或未给出,就假定为80。它的语义即:已识别的资源存放于正在监听tcp链接的
那个端口的服务器上,而且请求资源的的Request-UR为绝对路径(5.1.2节)。不管什么可能
的时候,URL 里使用IP 地址都是应该避免的(参看RFC 1900 [24])。若是绝对地址
(abs_path)没有出如今URL 里,那么应该给出"/"。若是代理(proxy)收到一个主机
(host)名,可是这个主机名不是全称域名(fully quanlified domain name),则代理应该把
它的域名加到主机名上。若是代理(proxy)接收了一个全称域名,代理不能改变主机(host)
名称。
3.2.3 URI 比较
当比较两个URI是否匹配时,客户应该对整个URI比较时应该区分大小写,而且一个字节一
个字节的比较。 但下面有些特殊状况:
- 一个为空或未给定的端口等同于URI-refernece(见RFC 2396)里的默认端口;
- 主机(host)名的比较必须不区分大小写;
- 模式(scheme)名的比较必须是不区分大小写的;
- 一个空绝对路径(abs_path)等同于"/"。
除了“保留(reserved)”和“不安全(unsafe)”字符集里的字符(参见RFC 2396
[42]) ,其它字符和它们的"%HEXHEX"编码的效果同样。
例如,如下三个URI是等同的:
http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html
3.3 日期/时间格式(Date/Time Formats)
3.3.1 完整日期 (Full Date)
HTTP应用曾经一直容许三种不一样日期/时间格式:
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
第一种格式是做为Internet 标准提出来的,它是一个国定长度的,由RFC 1123 [8](RFC
822[9]的升级版本)定义的一个子集。第二种格式使用比较广泛,可是基于废弃的RFC 850
[12]协议,而且没有年份。若是HTTP/1.1客户端和服务器要解析日期,他们必须能接收全部三
种格式(为了兼容HTTP/1.0),可是它们只能用RFC 1123 里定义的日期格式来填充头域
(header field)的值里用到HTTP-date的地方。
注:日期值的接收者被鼓励能可靠地接收来自于非HTTP应用程序发送的的日期值,例若有时
能够经过代理(proxy)/网关(gateway)向SMTP或NNTP获取或提交消息。
全部的HTTP日期/时间都必须以格林威治时间(GMT)表示。对HTTP而言,GMT彻底等同
于UTC(世界协调时间)。前两种日期/时间格式里包含“GMT”,它是时区的三个字面的简写,
而且当读到一个asctime格式时必须先被假定是GMT时间。HTTP日期(HTTP-date)区分大
小写,不能在此语法中除SP以外包含一个多余的LWS。
HTTP-date = rfc1123-date | rfc850-date | asctime-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
rfc850-date = weekday "," SP date2 SP time SP "GMT"
asctime-date = wkday SP date3 SP time SP 4DIGIT
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
date2 = 2DIGIT "-" month "-" 2DIGIT
; day-month-year (e.g., 02-Jun-82)
date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
; month day (e.g., Jun 2)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" | "Tue" | "Wed"
| "Thu" | "Fri" | "Sat" | "Sun"
weekday = "Monday" | "Tuesday" | "Wednesday"
| "Thursday" | "Friday" | "Saturday" | "Sunday"
month = "Jan" | "Feb" | "Mar" | "Apr"
| "May" | "Jun" | "Jul" | "Aug"
| "Sep" | "Oct" | "Nov" | "Dec"
注意:HTTP对日期/时间格式的要求仅仅应用在协议流的使用。客户和服务器没必要把这种格式
应用于用户呈现(user presentation),请求记录日志,等等。.
3.3.2 Delta Seconds (秒间隔)
一些HTTP头域(header field)容许时间值以秒为单位,以十进制整数表示,此值表明消息
接收后的时间。
delta-seconds = 1*DIGIT
3.4 字符集 (Character Sets)
HTTP使用术语“字符集”的定义,这和MIME中所描述的是同样.
本文档中的术语“字符集”涉及到一种方法,此方法是用单个或多个表将一个字节序列转换成
一个字符序列(译注:从这里来看,这应该是一种映射关系,表保存了映射关系)。注意在反
方向上无条件的转换是不成立的,由于并非全部的字符都能在一个给定的字符集里获得,一
个字符集里可能提供多个字节序列表征一个特定的字符。这个定义为的是容许不一样种类的字符
编码从单一简单表映射(如US-ASCII)到复杂表的转换方法,例如利用ISO-2022技术。然而,
相关于MIME字符集名字的定义必需要充分指定从字节到字符的映射。特别是利用外部外围信
息来精确肯定映射是不容许的.
注:这里使用的术语“字符集”通常的被称做一种“字符编码”。不过既然HTTP和MIME在
同一机构注册,术语统一是很重要的。
HTTP字符集的标记(token)是用不区分大小写的。全部的标记由IANA字符集注册机构[19]定
义。
charset = token
尽管HTTP容许用任意标记(token)做为字符集(charset)值,但这个标记已经在IANA字
符集注册机构注册过了,那么这个标记必须表明在该注册机构定义的字符集。对那些非IANA定
义的字符集,应用程序应该限制使用。
HTTP协议的实现者应该注意IETF字符集的要求[38][41].
3.4.1 丢失字符集(Missing Charset)
一些HTTP/1.0 应用程序当他们解析Content-Type 头时,当发现没有字符集参数(charset
parameter,译注: Content-Type: text/plain; charset=UTF-8,此时charset=UTF-8就是字符集
参数)可用时,这意味着接收者必须猜想实体主体(entity body)的字符集究竟是什么。若是
发送者但愿避免这种状况,他应该在Content-Type头域里包含一个字符集参数,即便字符集
是ISO-8859-1的也应该指明,这样就不会让接收者产生混淆。
不幸的是,一些旧的HTTP/1.0客户端不能处理在Content-Type头域里明确指定的字符集参数。
HTTP/1.1接收端必需要认真对待发送者提供的字符集;而且当用户代理(user agent,译注:
如浏览器)开始呈现一个文档时,虽然用户代理能够猜想文档的字符集,但若是content-type
头域里提供了字符集,而且用户代理也支持这种字符集的显示,无论用户代理是否愿意,它必
需要利用这种字符集。参见3.7.1节。
3.5 内容编码(Content Codings)
内容编码(content coding)的值表示一种曾经或能被应用于一个实体的编码转换(encoding
transformation)。内容编码主要用于文档的压缩或其它有效的变换,但这种变换必须不能丢失
文档的媒体类型的特性,而且不能丢失文档的信息(译注:就像有损压缩和无损压缩,前者不
会丢失信息,后者会丢失信息)。实体常常被编码后保存,而后传送出去,而且在接收端被解
码。
content-coding = token
全部内容编码(content-coding)的值是不区分大小写的。HTTP/1.1在接受译码 (Accept-
Encoding,14.3 节)和内容译码(Content-Encoding)(14.11 节)头域里使用内容编码
(content-coding)的值。尽管该值描述了内容编码,更重要的是它指出了一种解码机制,利用
这种机制对实体的编码进行解码。
网络分配数字权威( (IANA)充当内容编码的值标记(token)注册机构。最初,注册表里包
含下列标记:
gzip(压缩程序)
一种由文件压缩程序"gzip"(GNU zip)产生的编码格式(在RFC 1952中描述)。这种编码格
式是一种具备32位CRC的Lempel-Ziv编码(LZ77)。
compress(压缩)
一种由UNIX文件压缩程序"compress"产生的编码格式。这种编码格式是一种具备可适应性的
Lempel-Ziv-Welch编码(LZW)。
对于未来的编码,用程序名识表征编码格式是不可取。在这里用到他们是由于他们在历史的做
用,虽然这样作并很差。为了同之前的HTTP 实现相兼容,应用程序应该将"x-gzip"和"xcompress"
分别等同于"gzip"和"compress"。
deflate(缩小) 
deflate编码是由RFC 1950 [31]定义的"zlib"编码格式与RFC 1951 [29]里描述的"deflate"压缩
机制的组合的产物。
identity(一致性)
Identity是缺省编码;指明这种编码代表不进行任何编码转换。这种内容编码仅被用于接受译码
(Accept-Encoding)头域里,但不能被用在内容译码(Content-Encoding)头域里。.
新的内容编码的值标记(token)应该被注册;为了实现客户和服务器间的互操做性,实现新
值的内容编码算法规范应该能公开利用而且能独立实现,而且与本节中被定义的内容编码目的
相一致。
3.6 传输编码 (Transfer Codings)
传输编码(transfer-coding ,译注:transfer coding和和transfer-coding这两个术语在本协议
规范里所表达的意思其实没什么太大区别,“transfer-coding”可能更能表达语意,由于它是规
则中的规则名)的值被用来表示一个曾经,可以,或可能应用于一个实体的编码转换,传输编
码是为了可以确保网络安全传输。这不一样于内容编码(content coding),由于传输编码
(transfer coding)是消息的属性而不是实体的属性。
transfer-coding = "chunked" | transfer-extension
transfer-extension = token *( ";" parameter )
参数(parameter)采用属性/值对的形式.
parameter = attribute "=" value
attribute = token
value = token | quoted-string
全部传输编码的值是大小写不敏感。传输编码的值在TE 头域(14.39 节)和在传输译码
(Transfer-encoding) 头域中(14.41节)被运用。
不管什么时候,传输编码(transfer-coding)应用于一个消息主体(message body)时,若是存在
多个传输编码,则这些传输编码中必须包括“块”("chunked")传输编码,除非经过关闭连
接而使消息结束。当“块”(“chunked”)传输编码被用于传输编码时,它必须是应用于消息
主体的最后传输编码。"块"("chunked")传输编码最多只能用于消息主体(message-body)
一次。规定了上述规则后,接收者就能够肯定消息的传输长度(transfer-length)(4.4节)
传输编码与MIME[7]的内容传输译码(Content-Transfer-Encoding,MIME [7])的值类似,它
被定义可以实如今7位传输服务上保证二进制数据的安全传输。不过,传输编码与内容传输译
码(Content-Transfer-Encoding)对纯8位传输协议有不一样的侧重点。在HTTP中,消息主体
存在不安全的特性是由于有时候很难肯定消息主体的长度(7.2.2节)和在共享的传输上加密
数据。
网络分配数字权威(IANA)担任注册传输编码的值标记(token)的角色。起初,注册包含以下
标记:"块"(3.6.1 节),"身份"(3.6.2 节),"gzip"(3.5 节),"压缩"(3.5 节),和"缩小"(3.5
节).
新的传输编码的值标记应该注册,这同新的内容编码的值标记也须要注册同样。.
若是接收端接收到一个通过传输编码编码过的实体主体(entity body)但它不能对这个编码后
的实体主体进行解码,那么它应返回501(不能实现),而且要关闭链接。服务器不能向
HTTP/1.0客户端发送传输编码.。
3.6.1 块传输编码(Chunked Transfer Coding)
块编码(chunked encoding)改变消息主体使消息主体(message body)成块发送。每个块
有它本身的大小(size)指示器,在全部的块以后会紧接着一个可选的包含实体头域的尾部
(trailer)。这种编码容许发送端能动态生成内容,并能携带能让接收端判断消息是否接收完整
的有用信息。
Chunked-Body(块正文) = *chunk(块)
last-chunk(最后块)
trailer(尾部)
CRLF
chunk(块) = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
chunk-size是用16 进制数字字符串。块编码(chunked encoding)以大小为0的块结束,紧接
着是尾部(trailer),尾部以一个空行终止。
尾部(trailer)容许发送端在消息的末尾包含额外的HTTP头域(header field)。Trailer头域
(Trailer header field,在14.40 节阐述)来指明哪些头域被包含在块传输编码的尾部
(trailer) (见14.40节)
若是服务器要使用块传输编码进行响应,除非如下至少一条为真时它才能包含尾部
(trailer):
a)若是此响应的对应请求包括一个TE头域,而且利用 “trailers”指明了块传输编码响应的尾
部是能够接受的(TE头域在14.39节中描述;或者
b)若是是源服务器进行响应,响应里trailer字段里所有包含的是可选的元信息,而且接收端
接收此块传输编码响应时可能不会理会响应的尾部(以一种源服务器是能够接受的方式)。换
句话说,源服务器原意接受尾部(trailer)可能会在到达客户端时被丢弃的可能性。
当消息被一个HTTP/1.1(或更高版本)的代理(proxy)接收并转发到一个HTTP/1.0接收端
的时候,此要求防止了一种互操做性的失败。
在附录19.4.6节介绍了一个例子,这个例子介绍怎样对一个块主体(chunked-body)进行解
码。
全部HTTP/1.1应用程序必须能接收和解码以块(chunked)传输编码进行编码的消息主体,
而且必须能忽略它们不能理解的块扩展(chunk-extentsion)。
3.7 媒体类型(Media Type)
为了提供开放的,可扩展的数据类型和类型协商,HTTP在Content-Type(14.17节)实体头
域和Accept请求头域里利用了网络媒体[17]类型。
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token
参数(parameter)以一种 属性/值(attribute/value)形式(如3.6节定义)跟随 类型/子类型
(type/subtype)。
类型(type),子类型(subtype),和参数(parameter)里属性名称是大小写不敏感的。参
数值有多是大小写敏感的,也可能不是,这根据参数里属性名称的语意。线性空白(LWS)
不能被用于类型(type)和子类型(subtype)之间,也不能用于参数的属性和值之间。参数的
出现或不出现对处理媒体类型(media-type)可能会有帮助,这取决于它在媒体类型注册表里
的定义。
注意一些旧的HTTP应用程序不能识别媒体类型的参数(parameter)。当向一个旧HTTP应用
程序发送数据时,发送端只有在被type/subtype定义里须要时才使用类型参数(parameter)。
媒体类型(media-type)值须要被注册到网络数字分配权威(IANA[19])里。媒体类型的注册
程序在RFC 1590[17]中大概描述。使用未经注册的媒体类型是不被鼓励的。
3.7.1 规范化和文本缺省 (Canonicalization and Text Defaults)
网络媒体类型以一种规范化格式被注册。一个实体主体(entity-body)经过HTTP消息传输,
在传输前必须以一种合适的规范化格式来表示,但除了文本类型(text type),文本类型将会
在下一段阐述。
当消息以一种规范化格式表现时,文本类型的子类型(subtype)会运用GRLF做为文本里的
换行符。HTTP放松了这个要求,容许文本媒体以一个CR或LF表明一个换行符传输,而且如
果这样作的话就要贯穿整个实体主体(entity-body)。HTTP应用程序必须能接收CRLF,CR
和LF做为在文本媒体一个换行符。另外,若是文本里所属的字符集(character set)不能利用
字节13和10来分别地表示CR和LF,这是由于存在一些多字节字符集,HTTP容许应用字符
集里等价于CR和LF的字节序列来表示换行符。对换行符的灵活处理只能应用于实体主体里的
文本媒体;在HTTP消息控制结构(如头域和多边界体(multipart boundaries))里,一个纯
粹的CR或LF都不能代替CRLF的做用。
若是一个实体主体(entity-body)用内容编码(content-coding)进行编码,原始数据在被编
码前必须是一种以上定义的媒体类型格式。.
"charset"参数(parameter)被应用于一些媒体类型,来定义数据的字符集(见3.4节)。当发
送端没有指明charset参数(parameter)时,“text”类型的子媒体类型(subtype)被接收端
接收后会被认为是缺省的ISO-8859-1字符集。非“ISO-8859-1”字符集和它的子类(subsets)
的数据必须被指示恰当的字符集。3.4.1节描述了兼容性问题。
3.7.2 多部分类型(Multipart type)
MIME提供了一系列“多部分”(multipart)类型---在单个消息主体内包装一个或多个实体。所
有的多部分类型共享一个公共的语法(这在RFC 2046[40]的5.1.1节中描述),而且包含一个
边界(boundary)参数做为多部分媒体类型的值的一部分。多部分类型的消息主体是一个协议
元素,而且必须用CRLF来标识体部分(body-part,译注:见RFC 2046 的5节)之间的换行。
不一样于RFC 2046 里的多部分消息类型的描述,HTTP1.1 规定任何多部分类型的消息尾声
(epilogue,译:见RFC 2046对多部分消息类型的规则描述)必须不能存在;HTTP应用程
序不能传输尾声(epilogue)(即便原始的多部分消息尾部包含一个尾声)。存在这些限制是
为了保护多部分消息主体的自我定界的特性,由于多部分边界的结束(译注:根据RFC2046
中定义,多部分边界结束后可能还会有尾声)标志着消息主体的结束。
一般,HTTP把一个多部分类型的消息主体(message-body)和任何其它媒体类型的消息主
体等同对待:严格看做有用的负载体。有一个例外就是“multipart/byterange”类型(附录
19.2),当它出如今206(部份内容)响应时,此响应会被一些HTTP缓存机制解析,缓存机
制将会在13.5.4节和14.16节介绍。在其它状况下,一个HTTP用户代理会遵循MIME用户代
理同样或者类似的行为,这依赖于接收何种多部分类型。一个多部分类型消息的每个体部分
(body-part)里的MIME头域对于HTTP除了MIME语意并无太大意义。
一般, 一个HTTP用户代理应该遵循与一个MIME用户代理相同或类似的行为。若是一个应用
程序收到一个不能识别的多部分子类型,这个应用程序必须将它视为"multipart/mixed"。
注:"multipart/form-data"类型已经被特别地定义用来处理Post请求方法传送的窗体数据,这
在RFC 1867[15]里定义。
3.8 产品标记 (product Tokens)
产品标记用于使通讯应用软件能经过软件名称和版原本标识本身。不少头域都会利用产品标记,
这些头域容许构成应用程序重要部分的子产品能以空白分隔去列举。一般为了识别应用程序,
产品以应用程序的重要性的顺序来列举的。
product = token ["/" product-version]
product-version = token
例:
User-Agent:CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4
产品标记应言简意赅。它们不能用来作广告或其余不重要的信息。虽然任一标记可能出现
product-version 里,但这个标记仅能用来作一个版本 (i.e., 同产品中的后续版本应该在
product-version上有区别)
3.9 质量值(Quality Values)
HTTP内容协商(content negotiation,12节介绍)运用短“浮点”数字(short floating point
number)来表示不一样协商参数的相对重要性。重要性的权值被规范化成一个从0到1的实数。0
是最小值,1是最大值。若是一个参数的质量值(quanlity value)为0,那么这个参数的内容对
客户端来讲是不被接受。HTTP/1.1应用程序不能产生多于三位小数的实数。下面规则限定了这
些值。
qvalue = ( "0" [ "." 0*3DIGIT ] )
| ( "1" [ "." 0*3("0") ] )
"质量值" 是一个不当的用词,由于这些值仅仅表示相对等级。
3.10 语言标签 (Language Tags)
一个语言标签表征一种天然语言,这种天然语言能说,能写,或者被用来人与人之间的沟通。
计算机语言明显不包括在内的。HTTP在Accept-Language和Content-Language头域里应用
到语言标签(language tag)。
HTTP语言标签的语法和注册和RFC 1766[1]中定义的同样。总之,一个语言标签是由一个部分
或多部分构成:一个主语言标签和可能为空的多个子标签。
Language-tag = primary-tag*("-" subtag)
primary = 1*8ALPHA
subtag = 1*8ALPHA
标签中不容许出现空格,标签大小写不敏感(case-insensitive)。由IANA来管理语言标签中
的名字。典型的标签包括:
en, en-US, en-cockney, i-cherokee, x-pig-latin
上面的任意两个字母的主标签是一个ISO-639语言的缩写,而且两个大写字母的子标签是一个
ISO-3166的国家代码。(上面的最后三个标签是未经注册的标签;可是除最后一个以外全部的
标签都会未来注册)。
3.11 实体标签 (Entity Tags)
实体标签被用于比较相同请求资源中两个或更多实体。HTTP/1.1 在ETag(14.19节),Ifmatch(
14.24节),If-None-match(14.26节)和If-Rang(14.27节)头域中运用实体标签。
关于它们怎样被看成一个缓存验证器(cache validator)被使用和比较在13.3.3节被定义。一
个实体标签由一个给定的晦涩引用字符串(opaque quoted string),还可能前面带一个弱指
示器组成。
entity-tag = [ weak ] opaque-tag
weak = "W/"
opaque-tag = quoted-string
一个“强实体标签”若是被一个资源的两个实体里共享,那么这两个实体必须在字节上等价。
一个“弱实体标签”是以"W/"前缀的,它可能会被一个资源的两个实体共享,若是这两个实体
是等价的,而且能彼此替换,而且替换后也不会在语义上发生太大改变。一个弱实体标签只能
用于弱比较(weak comparison)。
在一个特定资源的全部实体版本里,一个实体标签必须能惟一。一个给定的实体标签值能够被
用于不一样的URI请求的实体。相同实体标签的值应用于不一样URI请求的实体,并不意味着这些
实体是等价的。
3.12 范围单位(Range Units)
HTTP/1.1 容许客户请求响应实体的一部分。HTTP/1.1 在Range(14.35 节)和Content-
Range(14.16节)头域里应用范围单位(range units)。任何实体根据不一样结构化单元都能被
分解成子范围
range-unit = bytes-unit | other-range-unit
bytes-unit = "bytes"
other-range-unit = token
HTTP/1.1中定义的惟一的范围单位是"bytes"。HTTP/1.1实现可能忽略其余单位指定的范围。
HTTP/1.1被设计容许应用程序实现不依赖于对范围的了解。
4 HTTP消息
4.1 消息类型(Message Types)
HTTP消息由从客户到服务器的请求消息和从服务器到客户的响应消息两部分组成.
HTTP-message = Request|Response ;HTTP/1.1
请求(第5节)和响应(第6节)消息利用RFC 822[9]定义的经常使用消息的格式,这种消息格式
是用于传输实体(消息的负载)。两种类型的消息都由一个开始行(start-line),零个或更多
个头域(常常被称做“头”),一个指示头域结束的空行(也就是以一个CRLF为前缀的什么
也没有的行),最后一个无关紧要的消息主体(message-body)组成。
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line
为了健壮性,服务器应该忽略任意请求行(Request-Line)前面的空行。换句话说,若是服务
器开始读消息流的时候发现了一个CRLF,它应该忽略这个CRLF。
通常一个存在问题的HTTP/1.0客户端会在POST请求消息以后添加额外的CRLF。为了从新声
明被BNF明确禁止的行为,一个HTTP/1.1客户端不能在请求前和请求后附加一些没必要要的
CRLF。
4.2 消息头 (Message Headers)
HTTP头域包括经常使用头域(4.5 节),请求头域(5.3 节),响应头域(6.2 节)和实体头域
(7.1节)。它们遵循的是RFC822[0]3.1节中给出的同一个经常使用格式。每个头域由一个名字
(域名)跟随一个":"和域值构成。域名是大小写不敏感的。域值前面可能有任意数量的LWS的。
但SP(空格)是首选的。头域能被延伸多行,这经过在这些行前面加一些SP或HT。应用程序
当产生HTTP消息时,应该遵循“经常使用格式”,由于可能存在一些应用程序,他们不能接收任
何经常使用形式以外的形式。.
message-header = field-name ":" [ field-value ]
field-name = token
field-value = *( field-content | LWS )
field-content = <the OCTETs making up the field-value
and consisting of either *TEXT or combinations
of token, separators, and quoted-string>
filed-content 不包括任何前导或后续的LWS(线性空白):线性空白出如今域值(filedvalue)
的第一个非空白字符以前或最后一个非空白字符以后。前导或后续LWS可能会在不会
改变域值语意状况下被删除。任何出如今filed-content之间的LWS可能在解析域值以前或把这
个消息往下流传递时会被一个SP代替。.
不一样域名的头域被接收的顺序是不重要的。然而,首先发送经常使用头域,而后紧接着是请求头域
或者是响应头域,而后是以实体头域结束,这样作是一个好的的方法。
若是一个头域的域值被定义成一个以逗号隔开的列表,那么使用同一个域名(filed-name)的
多个消息头域可能会出如今一些消息中。不改变消息的语义,能够把相同名的多个头域结合成
一个“域名:域值”对的形式,这能够经过把每个后续的域值加到第一个里,每个域值用
逗号隔开的算法实现。同名头域的接收顺序对合并的域值的解释是有重要意义的,因此代理
(proxy)当把消息转发时不能改变域值的顺序。
4.3 消息主体 (Message Body)
HTTP 消息的消息主体用来承载请求和响应的实体主体(entity-body)的。这些消息主体
(message-body)仅仅当被传输译码头域(Transfer-Encoding)指明的传输编码(transfercoding)
应用于实体主体(entity-body)时才和实体主体相区别,其它状况消息主体和实体主
体相同。传输译码头域在14.41节阐述。
message-body=entity-body|<entity-body encoded as per Transfer-Encoding>
传输译码头域被用来指明应用程序的传输编码,它是为了保证消息的安全和合适的传输。传输
译码(Transfer-Encoding)头域是消息的属性,而不是实体的属性,所以可能会沿着请求/响
应链被添加或删除。(然而,3.6节描述了一些限制当使用某个传输编码时)
何时消息主体(message-body)容许出如今消息中,这根据不一样请求和响应来决定的。
请求中消息主体(message-body)的存在是被请求中消息头域中是否存在内容长度
(Content-Length)或传输译码(Transfer-Encoding)头域来通知的。一个消息主体
(message-body)不能被包含在请求里若是某种请求方法(见5.1.1节)不支持请求里包含实
体主体(entity-body)。一个服务器应该能阅读或再次转发请求里的消息主体;若是请求方法
不容许包含一个实体主体(entity-body),那么当服务器处理这个请求时消息主体应该被忽略。
对于响应消息,消息里是否包含消息主体依赖相应的请求方法和响应状态码。全部HEAD请求
方法的请求的响应消息不能包含消息主体,即便实体头域出如今请求里。全部1XX(信息的),
204(无内容的)和304(没有修改的)的响应都不能包括一个消息主体(message-body)。
全部其余的响应必须包括消息主体,即便它长度可能为零。
4.4 消息的长度(Message Length)
当消息主体出如今消息中时,一条消息的传输长度(transfer-length)是消息主体(messagebody)
的长度;也就是说在实体主体被应用了传输编码(transfer-coding)后。当消息中出现
消息主体时,消息主体的传输长度(transfer-length)由下面(以优先权的顺序)决定::
1。任何不能包含消息主体(message-body)的消息(这种消息如1xx,204和304响应和任
何HEAD方法请求的响应)老是被头域后的第一个空行(CRLF)终止,无论消息里是否存在
实体头域(entity-header fields)。
2。若是Transfer-Encoding头域(见14.41节)出现,而且它的域值是非”“dentity”传输编码
值,那么传输长度(transfer-length)被“块”(chunked)传输编码定义,除非消息由于经过
关闭链接而结束。
3。若是出现Content-Length头域(属于实体头域)(见14.13节),那么它的十进制值(以
字节表示)即表明实体主体长度(entity-length,译注:实体长度其实就是实体主体的长度,
之后把entity-length翻译成实体主体的长度)又表明传输长度(transfer-length)。Content-
Length 头域不能包含在消息中,若是实体主体长度(entity-length)和传输长度(transferlength)
二者不相等(也就是说,出现Transfer-Encodind头域)。若是一个消息即存在传输译
码(Transfer-Encoding)头域而且也Content-Length头域,后者会被忽略。
4。若是消息用到媒体类型“multipart/byteranges”,而且传输长度(transfer-length)另外也没
有指定,那么这种自我定界的媒体类型定义了传输长度(transfer-length)。这种媒体类型不能
被利用除非发送者知道接收者能怎样去解析它; HTTP1.1客户端请求里若是出现Range头域
而且带有多个字节范围(byte-range)指示符,这就意味着客户端能解析multipart/byteranges
响应。
一个Range请求头域可能会被一个不能理解multipart/byteranges的HTTP1.0代理(proxy)
再次转发;在这种状况下,服务器必须能利用这节的1,3或5项里定义的方法去定界此消息。
5。经过服务器关闭链接能肯定消息的传输长度。(请求端不能经过关闭链接来指明请求消息体
的结束,由于这样可让服务器没有机会继续给予响应)。
为了与HTTP/1.0应用程序兼容,包含HTTP/1.1消息主体的请求必须包括一个有效的内容长
度(Content-Length)头域,除非服务器是HTTP/1.1遵循的。若是一个请求包含一个消息主体
而且没有给出内容长度(Content-Length),那么服务器若是不能判断消息长度的话应该以
400响应(错误的请求),或者以411响应(要求长度)若是它坚持想要收到一个有效内容长
度(Content-length)。
全部的能接收实体的HTTP/1.1应用程序必须能接受"chunked"的传输编码(3.6节),所以当
消息的长度不能被提早肯定时,能够利用这种机制来处理消息。
消息不能同时都包括内容长度(Content-Length)头域和非identity传输编码。若是消息包括了
一个非identity的传输编码,内容长度(Content-Length)头域必须被忽略.
当内容长度(Content-Length)头域出如今一个具备消息主体(message-body)的消息里,
它的域值必须精确匹配消息主体里字节数量。HTTP/1.1用户代理(user agents)当接收了一个
无效的长度时必须能通知用户。
4.5 经常使用头域(General Header Fields)
有一些头域即适用于请求消息也适用于响应消息,可是这些头域并不适合传输实体。这些头域
只能应用于传输消息。
general-header = Cache-Control ; Section 14.9
| Connection ; Section 14.10
| Date ; Section 14.18
| Pragma ; Section 14.32
| Trailer ; Section 14.40
| Transfer-Encoding ; Section 14.41
| Upgrade ; Section 14.42
| Via ; Section 14.45
| Warning ; Section 14.46
经常使用头域名能被扩展,但这要和协议版本的变化相结合。然而,若是通讯里的全部参与者都认
同新的或实践性的头域是经常使用头域,那么它们可能就被赋于经常使用头域的语意。不被识别的头域
会被做为实体头(entity-header)头域来看待。
5 请求(Request)
一个请求消息是从客户端到服务器端的,在消息首行里包含方法,资源指示符,协议版本。
Request = Request-Line ; Section 5.1
*(( general-header ; Section 4.5
| request-header ; Section 5.3
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 4.3
5.1 请求行 (Request-Line)
请求行(Request-Line)是以一个方法标记开始,后面跟随Request-URI和协议版本(HTTPVersion),
最后以CRLF结束。元素是以SP字符分隔。除了最后的CRLF,CR或LF是不被允
许的。
Request-Line =Method SP Request-URL SP HTTP-Version CRLF
5.1.1方法 (Method)
方法标记(token)指明了在被Request-URI指定的资源上执行的方法。这种方法是大小写敏
感的。
Method = "OPTIONS" ;9.2节
| "GET" ;9.3节
| "HEAD" ;9.4节
|"POST" ;9.5节
|"PUT" ;9.6节
|"DELETE" ;9.7节
|"TRACE" ;9.8节
|"CONNECT" ;9.9节
| extension-method
Extension-method = token
资源所容许的方法由Allow头域指定(14.7节)。响应的返回码老是通知客户某个方法对当前
资源是不是被容许的,由于被容许的方法能被动态的改变。若是服务器能理解某方法但此方法
对请求资源不被容许的,那么源服务器应该返回405状态码(方法不容许);若是源服务器不
能识别或没有实现某个方法,那么服务器应返回501状态码(没有实现)。方法GET和HEAD
必须被全部通常的服务器支持。全部其它的方法是可选的;然而,若是上面的方法都被实现,
这些方法遵循的语意必须和第9章指定的相同。
5.1.2 请求URL(Request-URI)
Request-URI是一种通用资源标识符(3.2 节),而且它用于指定请求的请求资源。
Request-URI ="*" | absoluteURI | abs_path | authotity
Request-URI的四个选项依赖于请求的性质。星号“*”意味着请求不能应用于一个特定的资源,
只能应用于服务器自己,而且只能在方法不该用于一个资源的时候才被容许。举例以下
OPTIONS * HTTP/1.1
当向代理(proxy)提交请求时,绝对URI(absoluteRUI)格式是不可缺乏的。代理(proxy)
可能会被要求再次转发请求或者从一个有效的缓存(cache)里构造响应去响应请求。注意:代
理可能转发请求给另外一个代理或直接给被absoluteURI指定的源服务器。为了不循环请求,
代理(proxy)必须能识别全部的服务器名字,包括任何别名,本地的变化值,数字IP地址。
一个请求行(Request-Line)的例子以下:
GET http://www.w3.org/pub/www/TheProject.html HTTP/1.1
为了将来HTTP版本的全部请求能迁移到absoluteURI地址,全部基于HTTP/1.1的服务器必
须接受绝对absoluteURI形式的请求,即便HTTP/1.1客户端只为代理产生绝对absoluteURI
请求。
authority格式只被用于CONNECT方法(9.9节).
Request-URI大多数状况是被用于指定一个源服务器或网关(gateway)上的资源。这种状况下,
URI 的绝对路径(abs_path,见3.2.1 节)做为Request-URI 被传输,而且URI 网络位置
(authority)必须在Host头域里指出。例如:客户但愿直接从源服务器获取资源,这种状况下,
它可能会创建一个TCP链接,此链接是特定于主机“www.w3.org”的80端口的,这时会发送
下面行:
GET /pub/WWW/TheProject.html HTTP/1.1
Host:www.w3.org
接下来是请求的其余部分。注意绝对路径(absolute path)不能是空的;若是在原始URI里没
有出现绝对路径,必须给出"/"(服务器的根)。
Request-URI是以3.2.1节里指定的格式传输。若是Request-URI用"%HEX HEX"[42]编码,源
服务器为了解析请求必须能对它进行解码。服务器接收到一个无效的Request-URI时必须以一
个合适的状态码响应。
透明代理(proxy)不能重写接收到的Request-URI里的“abs_path”部分,当它转发此请求到
下一个内向服务器(inbound server,见1.3术语)时,但除了上面说的把一个空的abs_path
用一个”/”代替以外。
注:不重写的规则是为了防止代理(proxy)改变请求的原意,由于存在源服务器利用非保留
(non-reserved)的URI字符为相反的目的 。实现者应该知道某些低于HTTP/1.1版本的代理
(proxy)会重写Request-URI。
5.2请求资源的识别 (The Resource Identified by a Request)
请求资源的精肯定位是由请求里的Request-URI和Host头域决定的。
若是源服务器不容许资源根据请求的不一样主机来区分时,那么它能够会忽略Host头域的值,
当它决定经过HTTP/1.1 请求来识别资源的时候。(在HTTP/1.1 里关于对Host 的支持在
19.6.1.1节描述了其余的要求)。
一个源服务器若是必须基于请求主机来区分资源(这是由于存在虚拟主机(virtual hosts)和
虚拟主机名(vanity host names)),那么,对HTTP/1.1请求,它必须遵循下面的规则去决
定请求的资源:
1. 若是Request-URI是绝对地址(absoluteURI),那么主机(host)是Request-URI的
一部分。任何出如今请求里Host头域的值应当被忽略。
2. 假如Request-URI不是绝对地址(absoluteURI),而且请求包括一个Host头域,则主
机(host)由该Host头域的值决定.
3. 假如由规则1或规则2定义的主机(host)对服务器来讲是一个无效的主机(host),
则应当以一个400(坏请求)错误消息返回。
缺乏Host头域的HTTP/1.0请求的接收者可能会尝试去利用启发式的规则(例如:检查URI
路径是不是特定某个主机)去决定被请求的真正资源。
5.3请求头域 (Request Header Fields)
请求头域容许客户端传递请求的附加信息和客户端本身的附加信息给服务器。这些头域做为请
求的修饰,这和程序语言方法调用的参数语义是等价的。
请求头(request-header) = Accept ;14.1节
| Accept-Charset ;14.2节
|Accept-Encoding ;14.3节
|Accept-Language ;14.4节
|Authorization ;14.8节
|Expect ;14.20节
|From ;14.22节
|Host ;14.23节
|If-Match ;14.24节
|If-Modified-Since ;14.25节
| If-None-Match ;14.26节
| If-Range ;14.27节
| If-Unmodified-Since ;14.28节
| Max-Forwards ;14.31节
| Proxy-Authorization ;14.34节
| Range ;14.35节
| Referer ;14.36节
|TE ;14.39节
| User-Agent ;14.43节
请求头域的名字是能被扩展,但只能随协议版本改变而被扩展。然而新的或实践性的头域能够
给定请求头域语义,若是全部通讯方都把它看做请求头域。不能识别的头域会被看做实体头域
(entity-header)。
6 响应 (Response)
接收和解析一个请求消息后,服务器发出一个HTTP响应消息。
response =Status-Line ;6.1节
*(( general-header) ; 4.5节
| response-header ;6.2节
| entity-header)CRLF) ;7.1节
CRLF
[ message-body ] ;7.2节
6.1 状态行 (Status-Line)
响应消息的第一行是状态行(stauts-Line),由协议版本以及数字状态码和相关的文本短语组
成,各部分间用空格符隔开,除了最后的CRLF序列,中间不容许有CR或LF。
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
6.1.1状态码与缘由短语 (Status Code and Reason Phrase)
Status-Code元素是一个试图理解和知足请求的三位数字整数码,这些码的完整定义在第十章。
缘由短语(Reason-Phrase)是为了给出关于状态码的简单的文本描述。状态码用于控制,而
缘由短语(Reason-Phrase)是让用户便于阅读。客户端不须要检查和显示缘由短语。
状态码的第一位数字定义响应类别。后两位数字没有任何分类角色。第一位数字有五种值:
-1xx :报告的 -请求被接收到,继续处理
-2xx :成功 - 被成功地接收(received),理解(understood),接受
(accepted)的动做 。
-3xx :重发 - 为了完成请求必须采起进一步的动做。
-4xx :客户端出错 - 请求包括错的语法或不能被知足。
-5xx :服务器出错 - 服务器没法完成显然有效的请求。
下面列举了为HTTP/1.1定义的态码值,和对应的缘由短语(Reason-Phrase)的例子。缘由短
语在这里例举只是建议性的----它们也许被一个局部的等价体代替而不会影响此协议的语义。
Status-Code =
"100" ; 10.1.1节: 继续
|"101" ; 10.1.2节: 转换协议
|"200" ; 10.2.1节: OK
|"201" ; 10.2.2节: 已建立
|"202" ; 10.2.3节: 接受
|"203" ; 10.2.4节: 非权威信息
|"204" ; 10.2.5节: 无内容
|"205" ; 10.2.6节: 重置内容
|"206" ; 10.2.7节: 部份内容
|"300" ; 10.3.1节: 多个选择
|"301" ; 10.3.2节: 永久移动
|"302" ; 10.3.3节: 发现
|"303" ; 10.3.4节: 见其它
|"304" ; 10.3.5节: 没有被改变
|"305" ; 10.3.6节: 使用代理
|"307" ; 10.3.8节 临时重发
|"400" ; 10.4.1节: 坏请求
|"401" ; 10.4.2节: 未受权的
|"402" ; 10.4.3节: 必要的支付
|"403" ; 10.4.4节: 禁用
|"404" ; 10.4.5节: 没有找到
|"405" ; 10.4.6节: 方式不被容许
|"406" ; 10.4.7节: 不接受的
|"407" ; 10.4.8节: 须要代理验证
|"408" ; 10.4.9节: 请求超时
|"409" ; 10.4.10节; 冲突
|"410" ; 10.4.11节: 不存在
|"411" ; 10.4.12节: 长度必需
|"412" ; 10.4.13节;先决条件失败
|"413" ; 10.4.14节: 请求实体太大
|"414" ; 10.4.15节; 请求URI太大
|"415" ; 10.4.16节: 不被支持的媒体类型
|"416" ; 10.4.17节: 请求的范围不知足
|"417" ; 10.4.18节: 指望失败
|"500" ; 10.5.1节: 服务器内部错误
|"501" ; 10.5.2节: 不能实现
|"502" ; 10.5.3节: 坏网关
|"503" ; 10.5.4节: 服务不能得到
|"504" ; 10.5.5节: 网关超时
|"505" ; 10.5.6节: HTTP版本不支持
|扩展码
extension-code =3DIGIT
Reason-Phrase = *<TEXT,excluding CR,LF>
HTTP状态码是可扩展的。HTTP应用程序不须要理解全部已注册状态码的含义,尽管那样的理
解是很但愿的。可是,应用程序必须了解由第一位数字指定的状态码的类别,任何未被识别的
响应应被看做是那个类别的x00状态码,未被识别的响应不能被缓存除外。例如,若是客户端
收到一个未被识别的状态码431,则能够安全的认为请求有错,而且它会对待此响应就像它接
收了一个状态码是400的响应。在这种状况下,用户代理(user agent)应当把响应的实体展
现给用户,由于实体有可能包括人类可读的信息,这些信息也许能解释非正常状态的缘由。
6.2响应头域 (Response Header Fields)
响应头域容许服务器传送响应的附加信息,这些信息不能放在状态行(Status-Line)里.。这些
头域给出有关服务器的信息以及请求URI(Request-URI)指定资源的更进一步访问信息。
response-header = Accept-Ranges ; 14.5节
|Age ; 14.6节
|Etag ; 14.19节
|Location ; 14.30节
|Proxy-Autenticate ; 14.33节
|Retry-After ; 14.37节
|Server ; 14.38节
|Vary ; 14.44节
|WWW-Authenticate ; 14.47节
响应头域的名字能依赖于协议版本的变化而扩展。然而,新的或者实践性的头域可能会给予响
应头域的语义若是通讯全部成员都能识别他们并把他们看做响应头域。不被识别的头域被看做
实体头域。
7 实体(Entity)
若是不被请求方法或响应状态码所限制,请求和响应消息均可以传输实体。 实体包括实体头域
(entity-header)与实体主体(entity-body),而有些响应只包括实体头域(entity-header)。
在本节中的发送者和接收者是不是客户端或服务器,这依赖于谁发送或谁接收此实体。
7.1 实体头域(Entity Header Fields)
实体(entity-header)头域定义了关于实体主体的的元信息,或在无主体的状况下定义了请求
的资源的元信息。有些元信息是可选的;一些是必须的。
entity-header = Allow ; Section 14.7
| Content-Encoding ; Section 14.11
| Content-Language ; Section 14.12
| Content-Length ; Section 14.13
| Content-Location ; Section 14.14
| Content-MD5 ; Section 14.15
| Content-Range ; Section 14.16
| Content-Type ; Section 14.17
| Expires ; Section 14.21
| Last-Modified ; Section 14.29
| extension-header
extension-header = message-header
扩展头机制容许在不改变协议的前提下定义额外的实体头域,但不保证这些域在接收端可以被
识别。未被识别的头域应当被接收者忽略,且必须被透明代理(transparent proxy)转发。
7.2 实体主体(Entity Body)
由HTTP请求或响应发送的实体主体(若是存在的话)的格式与编码方式应由实体的头域决定。
Entity-body= *OCTET
如4。3节所述,实体主体(entity-body)只有当消息主体存在时时才存在。实体主体(entitybody)
从消息主体根据传输译码头域(Transfer-Encoding)解码获得,传输译码用于确保消
息的安全和合适传输。
7.2.1 类型(Type)
当消息包含实体主体(entity-body)时,主体的数据类型由实体头域的Content-Type 和
Content-Encoding头域肯定。这些头域定义了两层顺序的编码模型:
Entity-body:=Content-Encoding( Content-Type( data) )
Content-Type指定了下层数据的媒体类型。Content-Encoding可能被用来指定附加的应用于数
据的内容编码,常常用于数据压缩的目的,内容编码是请求资源的属性。没有缺省的编码。
任一包含了实体主体的HTTP/1.1消息都应包括Content-Type头域以定义实体主体的媒体类型。
若是只有媒体类型没有被Content-Type头域指定时,接收者可能会尝试猜想媒体类型,这通
过观察实体主体的内容而且/或者经过观察URI指定资源的扩展名。若是媒体类型仍然不知道,
接收者应该把类型看做”application/octec-stream”。
7.2.2 实体主体长度(Entity Length)
消息的实体主体长度指的是消息主体在被应用于传输编码(transfer-coding)以前的长度。4.4
节定义了怎样去肯定消息主体的传输长度。
8 链接
8.1 持久链接(Persistent Connection)。
8.1.1 目的
在没有持久链接以前,为获取每个URL指定的资源都必须创建了一个独立的TCP 链接,
这就加剧了HTTP服务器的负担,易引发互联网的阻塞。嵌入图片与其它相关数据一般使用户
在短期内对同一服务器进行屡次请求。目前针对这些性能问题的分析以及一个原型实现的结
果是能够得到的[26][30]。 HTTP/1.1(RFC2068)实现的实践过程和度量展示了一个满意的结
果。对其余方法也有了初步探究,如T/TCP [27]。
HTTP持久链接有着诸多的优势:
--- 经过创建与关闭较少的TCP链接,不只节省了路由器与主机(客户端,服务器,代理,网
关,隧道或缓存)的CPU时间,还节省了主机用于TCP协议控制块(TCP protocol control
blocks)的内存。
--- HTTP请求和响应能在链接上进行管线请求方式。 管线请求方式能容许客户端执行屡次请求
而不用等待每个请求的响应(译注:即客户端能够发送请求而不用等待之前的请求的响应到
来后再发请求),而且此时只有一个TCP链接被使用,从而提升了效率,减小了时间。
--- 网络阻塞会被减小,这是因为减小了因TCP链接产生的包的数量而且也因为容许TCP有充
分的时间去决定网络阻塞的状态。
--- 由于无须在建立TCP链接时的握手上耗费时间,而使后续请求的等待时间减小。
---HTTP改进的愈来愈优雅,由于报告错误不须要关闭tcp链接的代价。未来的HTTP版本客户
端能够乐观的尝试利用一个新特性,可是若是和老服务器通讯时错误被报告,那么就要用旧的
语义进行从新尝试。
HTTP实现应该实现持久链接。
8.1.2 整体操做
HTTP/1.1 与早期HTTP 版本的一个显著区别在于持久链接是HTTP/1.1的缺省方式。也就是说,
除非另有指定,客户端总应当假定服务器会保持持久链接,即使在收到服务器的出错响应时也
应如此。
持久链接提供了一种能够由客户端或服务器通知终止TCP链接的机制。利用Connection头域
(14。10节)能够产生终止链接信号。一旦出现了终止链接的信号,客户端便不可再向此链接
提出任何新请求。
8.1.2.1 协商(Negotiation)
除非请求里Connection头域中包含“close”链接标记(connection-token),HTTP/1.1服务器
总能够认为HTTP/1.1 客户端想要维持持久链接(persistent connection)。若是服务器想在发
出响应后当即关闭链接,它应当发送一个含“close”的Connection头域。
一个HTTP/1.1客户端可能指望链接一直保持开着,但这必须是基于服务器响应里是否包含一
个Connection头域而且此头域里是否包含“close”。若是客户端不想再继续维持链接来发送更
多请求,那么它应发送一个值为“close”的Connection头域。
若是客户端或服务器中的任一方在Connection头域里包含“close”,那么那个请求就成为这个
链接的最后一个请求。
客户端和服务器不该认为持久链接是低于1.1的HTTP版本所拥有的,除非它被显式地指明。
19.6.2节指出了跟HTTP/1.1客户端兼容的更多信息。
8.1.2.2 管线(pilelining)
支持持久链接(persistent conncetion)的客户端能够以管线的方式发送请求(即无须等待响
应而发送多个请求)。服务器必须按接收请求的顺序发送响应。
假定以持久链接方式进行链接,而且假定在链接创建后进行管线方式请求的客户端应该准备去
从新尝试链接若是首次管线请求方式尝试失败。若是客户端从新去尝试链接,那么,只有在客
户端知道链接是持久链接以后,客户端才能进行管线发送请求。若是服务器在响应全部对应的
请求以前关闭了链接,客户端必须准备去从新发送请求。
客户端不该该利用非等幂的方法或者非等幂的方法序列(见9.1.2节)进行管线方式的请求。否
则一个过早的传输层链接的终止可能会致使不肯定的结果。但愿发送非等幂方法请求的客户端
只有接收了上次它发出请求的响应后才能再次发送请求给服务器。
8.1.3 代理 (Proxy Servers)
代理是很是重要的,由于代理正确地实现了Connection头域的属性,这在14.10节指出了。
代理必须分别向它相连的客户端或源服务器(或其余的代理)指明持久链接。每个持久链接
只能应用于一个传输层链接。
代理不能和一个HTTP/1.0客户端创建一个HTTP/1.1持久链接(可是参见RFC2068[33]里的
关于许多HTTP/1.1客户端利用Keep-Alive头域的问题的讨论)。
8.1.4 实际考虑 (Practical Considerations)
服务器一般有一个时限值,超过必定时间即再也不维持处于非活动的链接。代理会选一个较高的
值,由于客户端极可能会与同一服务器创建多个链接。持久链接方式的采用对于客户端与服务
器来讲均未提出任何须须存在超时或给定多长时间的要求。
当客户端或服务器但愿超时时, 它应该优雅的去关闭传输链接。客户端与服务器端应始终注意
对方是否终止了传输层链接,并适当的予以响应。若客户端或服务器未能及时检测到对方已终
止了链接,将会形成没必要要的网络资源浪费。
客户端,服务器,或代理可能在任意时刻会终止传输链接。好比,客户端可能正想发出新的请
求,而此时服务器却决定关闭“闲置”的链接。在服务器看来,链接已经由于闲置被关闭了,
但客户端认为我正在请求。
这代表客户端,服务器与代理必须有能力从链接的异步终止事件中恢复。只要请求是等幂的
(见9.1.2节),客户端软件应该能从新打开传输层链接并重试传输遗弃的请求序列而不须要
用户进行去交互。对非等幂方法的请求就不能自动重试请求,尽管用户代理(user agent)可能
提供一我的工操做去重试这些请求。用户代理(user-agent)对应用程序语义理解的确认应该
替代用户的确认。若是再次重试请求序列失败,那么就不能再进行自动重试请求了。
服务器尽量应该至少在每次链接中响应一个请求。除非出于网络或客户端的故障,服务器不
应在传送响应的中途断开链接。
使用持久链接的客户端应限制与某一服务器同时链接的个数。单用户客户端不该与任一服务器
或代理保持两个以上的链接。代理应该与其它服务器或代理之间维护2*N个链接,其中N是同
时在线的用户数。这些准则是为了改善响应时间和和避免阻塞。
8.2 消息传送的要求(Message Transmission Requirements)
8.2.1 持久链接与流量控制 (Persistent Connections and Flow Control)
HTTP/1.1服务器应保持持久链接并使用TCP流量控制机制来解决临时过载,而不是在终止连
接后期望客户端的重试。后一方法会恶化网络阻塞。
8.2.2 监视链接中出错状态的消息
HTTP/1.1(或更新)客户端应该当在发送请求的消息主体时同时监视网络链接是否处于出错
状态。若客户端发现了错误,它应当当即中止消息主体的的传送。若消息主体是以块传输编码方
式发送的(3.6节),能够用长度为零的块和空尾部(trailer)来提早标记报文结束。若消息主
体以前有Content-Length头域,那么客户端必须关闭链接。
8.2.3 100状态码的用途
100状态码(继续,见10.1.1节)的目的在于容许客户端,在发送此请求消息主体前,断定服
务器是否愿意接受发送消息的主体(基于请求的头域)。 在有些状况下,若是服务器拒绝查看
消息主体,这时客户端发送消息主体是不恰当的或会大大下降效率。
HTTP/1.1客户端的要求:
--- 若客户端想要在发送请求消息主体以前等候100(继续)响应,则它必须发送一个Expect
请求头域(见14.20节),而且值是“100-continue”。
--- 客户端不能发送一个值是“100-continue”的Expect请求头域,若是此客户端不打算发送带
消息主体的请求。
因为存在旧实现,协议容许二义性的情形存在,这在客户端在发送“Expect:100-continue”后
而不必定要接收一个417(指望失败)状态码或着100(继续)状态码时。所以,当一个客户
端发送Expect请求头域给一个源服务器(可能经过代理),此服务器也没有以100(继续)
状态码响应,那么客户端不该该在发送请求消息的主体前无限等待。
HTTP/1.1源服务器的要求:
--- 当接收一个包含值为“100-contitue”的Expect请求头域的请求时,源服务器必须或者以
100(继续)状态码响应从而继续从输入流里接收数据,或者以一个最终的状态码响应。源服务
器不能在发送100(继续)状态码响应以前接收请求主体。若是服务器以一个终结状态码响应
后,它可能会关闭传输层链接或者它也可能会继续接收或遗弃剩余的请求。可是既然它返回了
一个终结状态码的响应,它就不能再去执行那个请求的方法(如:POST方法,PUT方法)。
--- 若是请求消息不含值为“100-continue”的Expect请求头域, 源服务器不该发送100(继
续)响应,而且,当请求来自HTTP/1.0(或更早)的客户端时,服务器也不得发送100(继
续)响应。对此规定有一例外:为了与RFC 2068兼容,源服务器可能会发送一个100(继
续)状态响应以响应HTTP/1.1的PUT或POSt 请求,虽然这些请求中没有包含值为”100-
continue”的Expect请求头域。这个例外的目的是为了减小任何客户端由于等待100(继续)状
态响应的延时,但此例外只能应用于HTTP/1.1请求,并不适合于其余HTTP版本的请求。
--- 若源服务器已经接收到部分或所有请求的消息的主体,源服务器能够不须要发100(继续)
响应。
---一旦请求消息主体被接收和被处理,发送100(继续)响应的源服务器必须最终能发送一个
终结状态响应,,除非源服务器过早切断了传输层链接。
--- 若源服务器接收到不含值为“100-contitue”的Expect请求头域的请求,但该请求含有请求
消息主体,而服务器在从传输层链接上接收整个请求消息主体前返回一个终结状态响应,那么
此源服务器不能关闭传输层链接直到它接收了整个请求或者直到客户端关闭了此链接。不然客
户端可能不会信任接收此响应消息。然而,这一要求不该该被解释为防止服务器免受拒绝服务
攻击,或者防止服务器被客户端攻击。
对HTTP/1.1代理的要求:
--- 若代理接到一个请求,此请求包含值为“100-continue”的Expect请求头域,而且代理可能
不能肯定下一站服务器是否遵循HTTP/1.1或更高版协议,那么它必须转发此请求时包含此
Expect头域。
--- 若代理知道下一站服务器版本是HTTP/1.0或更低,则它不能转发此请求,而且它必须以
417(指望失败)状态响应。
--- 代理应当维护一个缓存,以记录最近访问下一站点服务器的HTTP版本号。
--- 若接收到的请求来自于版本是HTTP/1.0(或更低)的客户端,而且此请求不含值为“100-
continue”的Expect请求头域,那么代理不能转发100(继续)响应。 这一要求可覆盖1xx响
应转发的通常规则(参见10.1节)。
8.2.4 服务器过早关闭链接时客户端的行为
若是HTTP/1.1 客户端发送一条含有消息主体的请求消息,但不含值为“100-continue”的
Expect请求头域,而且若是客户端没有直接与HTTP/1.1源服务器相连,而且客户端在接收到
服务器的状态响应以前看到了链接的关闭,那么客户端应该重试此请求。在重试时,客户端可
以利用下面的算法来得到可靠的响应。
1. 向服务器发起一新链接。
2. 发送请求头域。
3. 初始化变量R,使R的值为通往服务器的往返时间的估计值(好比基于创建链接的时间),
或在没法估计往返时间时设为一常数值5秒。
4. 计算T=R*(2**N),N为此前重试请求的次数。
5. 等待服务器出错响应,或是等待T秒(二者中时间较短的)。
6. 若没等到出错响应,T秒后发送请求的消息主体。
7. 若客户端发现链接被提早关闭,转到第1步,直到请求被接受,接收到出错响应,或是用
户因不耐烦而终止了重试过程。
在任意点上,客户端若是接收到服务器的出错响应,客户端
--- 不该再继续发送请求, 而且
--- 应该关闭链接若是客户端没有完成发送请求消息。
9 方法定义(Method Definitions)
HTTP/1.1经常使用方法的定义以下。虽然方法能够被展开,但新加的方法不能被认为与扩展客户端
和服务器共享一样的语义。
Host请求头域(见14.23节)必须能在全部的HTTP/1.1请求里出现。
9.1 安全和等幂(Idempotent)方法
9.1.1 安全方法(Safe Methods)
实现者应当知道软件是表明用户在互联网上进行交互,而且应该当心地容许用户知道任何它们
可能采起的动做(action),这些动做可能给他们本身或他人带来没法预料的结果。
GET和HEAD方法只是执行没有影响的动做那就是获取资源。这些方法应该被考虑是“安全”
的。可让用户代理调用的其它方法,如:POST,PUT,DELETE,这些方法是特殊的,用户
代理应该知道这些方法可能会执行不安全的动做。
天然的,保证当服务器因为执行GET请求而不能产生反作用是不可能的;实际上,一些动态
的资源会考虑这个特性。用户并无请求这些反作用,所以这些反作用对用户应该是不受影响
的。
9.1.2 等幂方法(Idempotent Mehtods)
方法能够有等幂的性质由于(除了出错或终止问题)N>0个相同请求的反作用同单个请求的副
做用的效果是同样(译注:等幂就是值不变性,相同的请求获得相同的响应结果,不会出现相
同的请求出现不一样的响应结果)。方法GET,HEAD,PUT,DELETE都有这种性质。一样,方
法OPTIONS和TRACE不该该有反作用,所以具备内在的等幂性。然而,有可能有多个请求的
请求序列是不等幂的,即便在那样的序列中全部方法都是等幂的。(若是整个序列总体的执行
的结果老是相同的,而且此结果不会由于序列的总体,部分的再次执行而改变,那么此序列是
等幂的。)例如,一个序列是非等幂的若是它的结果依赖于一个值,此值在之后相同的序列里
会改变。
根据定义,一个序列若是没有反作用,那么此序列是等幂的(假设在资源集上没有并行的操
做)。
9.2 OPTIONS(选项)
OPTIONS方法代表请求想获得请求/响应链上关于此请求里的URI(Request-URI)指定资源
的通讯选项信息。此方法容许客户端去断定请求资源的选项和/或需求,或者服务器的能力,而
不须要利用一个资源动做(译注:使用POST,PUT,DELETE方法)或一个资源获取(译注:
用GET方法)方法。
此方法的响应是不能缓存的.。
若是OPTIONS 请求消息里包括一个实体主体(当请求消息里出现Content-Length 或者
Transfer-Encoding头域时),那么媒体类型必须经过Content-Type头域指明。虽然此规范没
有定义如何使用此实体主体,未来的HTTP扩展可能会利用OPTIONS请求的消息主体去获得
服务器得更多信息。一个服务器若是不支持OPTION请求的消息主体,它会遗弃此请求消息主
体。
若是请求URI是一个星号("*"),,OPTIONS请求将会应用于服务器的全部资源而不是特定资
源。由于服务器的通讯选项一般依赖于资源,因此”*”请求只能在“ping”或者“no-op”方法时
才有用;它干不了任何事情除了容许客户端测试服务器的能力。例如:它能被用来测试代理是
否遵循HTTP/1.1。
若是请求URI不是一个星号("*"),,OPTIONS请求只能应用于请求URI指定资源的选项。
200响应应该包含任何指明选项性质的头域,这些选项性质由服务器实现而且只适合那个请求
的资源(例如,Allow头域),但也可能包一些扩展的在此规范里没有定义的头域。若是有响应
主体的话也应该包含一些通讯选项的信息。这个响应主体的格式并无在此规范里定义,可是
可能会在之后的HTTP里定义。内容协商可能被用于选择合适的响应格式。若是没有响应主体包
含,响应就应该包含一个值为“0”的Content-Length头域。
Max-Forwards请求头域可能会被用于针对请求链中特定的代理。当代理接收到一个OPTIONS
请求,且此请求的URI 为absoluteURI,而且此请求是能够被转发的,那么代理必需要检测
Max-Forwards头域。若是Max-Forwards头域的值为“0”,那么此代理不能转发此消息;而是
代理应该以它本身的通讯选项响应。若是Max-Forwards头域是比0大的整数值,那么代理必
须递减此值当它转发此请求时。若是没有Max-Forwards头域出如今请求里,那么代理转发此
请求时不能包含Max-Forwards头域。
9.3 GET
GET方法意思是获取被请求URI(Request-URI)指定的信息(以实体的格式)。若是请求
URI涉及到一个数据生成过程,那么这个过程生成的数据应该被做为实体在响应中返回而不是
过程的源文本,除非源文本刚好是过程的输出。
若是请求消息包含 If-Modified-Since,,If-Unmodified-Since,If-Match,If-None-Match 或者
If-Range头域,GET的语义将变成“条件(conditionall) GET”。一个条件GET方法会请求满
足条件头域的实体。条件GET方法的目的是为了减小没必要要的网络使用,这经过容许利用缓存
里仍然保鲜的实体而不用屡次请求或传输客户端已经拥有的实体来实现的。.
若是请求方法包含一个Range头域,那么GET方法就变成“部分Get”(partial GET)方法。
一个部分GET会请求实体的一部分,这在14.35节里描述了。 部分GET方法的目的是为了减
少没必要要的网络使用,能够容许客户端从服务器获取实体的部分数据,而不须要获取客户端本
地已经拥有的部分实体数据。
GET请求的响应是可缓存的(cacheable)若是此响应知足第13节HTTP缓存的要求。
看15.1.3节关于GET请求用于表单时安全考虑。
9.4 HEAD
HEAD 方法和GET 方法一致,除了服务器不能在响应里返回消息主体。HEAD请求响应里
HTTP头域里的元信息(译注:元信息就是头域信息)应该和GET请求响应里的元信息一致。
此方法被用来获取请求实体的元信息而不须要传输实体主体(entity-body)。此方法常常被用
来测试超文本连接的有效性,可访问性,和最近的改变。.
HEAD请求的响应是可缓存的,由于响应里的信息可能被缓存用于更新之前那个资源对应缓存
的实体.。若是出现一个新的域值指明缓存的实体和当前源服务器上的实体有所不一样(可能由于
Content-Length,Content-MD5,ETag或Last-Modified值的改变),那么缓存(cache)必
须认为缓存项是过期的(stale)。
9.5 POST
POST 方法被用于请求源服务器接受请求中的实体做为请求资源的一个新的从属物。POST被
设计涵盖下面的功能。
--已存在的资源的注释;
--发布消息给一个布告板,新闻组,邮件列表,或者类似的文章组。
--提供一个数据块,如提交一个表单给一个数据处理过程。
--经过追加操做来扩展数据库。
POST方法的实际功能是由服务器决定的,而且常常依赖于请求URI(Request-URI)。POST
提交的实体是请求URI的从属物,就好像一个文件从属于一个目录,一篇新闻文章从属于一个
新闻组,或者一条记录从属于一个数据库。
POST方法执行的动做可能不会对请求URI所指的资源起做用。在这种状况下,200(成功)或
者204(没有内容)将是适合的响应状态,这依赖于响应是否包含一个描述结果的实体。
若是资源被源服务器建立,响应应该是201(Created)而且包含一个实体,此实体描述了请
求的状态。而且引用了这个新资源和一个Location头域(见14.30节)。
POST方法的响应是不可缓存的。除非响应里有合适的Cache-Control或者Expires头域。然而,
303(见其余)响应能被用户代理利用去得到可缓存的响应。
POST 请求必须遵循8.2节里指明的消息传送的要求。
参见15.1.3节关于安全性的考虑.
9.6 PUT
PUT方法请求服务器去把请求里的实体存储在请求URI(Request-URI)标识下。若是请求
URI(Request-URI)指定的的资源已经在源服务器上存在,那么此请求里的实体应该被看成
是源服务器关于此URI所指定资源实体的最新修改版本。若是请求URI(Request-URI)指定
的资源不存在,而且此URI被用户代理定义为一个新资源,那么源服务器就应该根据请求里的
实体建立一个此URI所标识下的资源。若是一个新的资源被建立了,源服务器必须能向用户代
理(user agent) 发送201(已建立)响应。若是已存在的资源被改变了,那么源服务器应该
发送200(Ok)或者204(无内容)响应。若是资源不能根据请求URI建立或者改变,一个合
适的错误响应应该给出以反应问题的性质。实体的接收者不能忽略任何它不理解和不能实现的
Content-*(如:Content-Range)头域,而且必须返回501(没有被实现)响应。
若是请求穿过一个缓存(cache),而且此请求URI(Request-URI)指示了一个或多个当前
缓存的实体,那么这些实体应该被看做是旧的。PUT方法的响应是不可缓存的。
POST方法和PUT方法请求最根本的区别是请求URI(Request-URI)的含义不一样。POST请
求里的URI 指示一个能处理请求实体的资源(译注:此资源多是一段程序,如jsp 里的
servlet) 。此资源多是一个数据接收过程,一个网关(gateway,译注:网关和代理的区别
是:网关能够进行协议转换,而代理不能,只是起代理的做用,好比缓存服务器其实就是一个
代理),或者一个单独接收注释的实体。对比而言,PUT方法请求里的URI标识请求里封装的
实体一一用户代理知道URI 意指什么,而且服务器不能把此请求应用于其它资源
(resource)。若是服务器指望请求被应用于一个不一样的URI,那么它必须发送301(永久移
动)响应;用户代理能够本身决定是否重定向请求。
一个单独的资源可能会被许多不一样的URI指定。如:一篇文章可能会有一个URI指定当前版本,
而这个URI区别于这篇文章其它特殊版本的URI。这种状况下,对一个通用URI的PUT请求可
能会致使其资源的其它URI请求被源服务器重定义。
HTTP/1.1没有定义PUT方法对源服务器的状态影响。
PUT请求必须遵循8.2节中的消息传送的要求。
除非特别指出,PUT方法请求里的实体头域应该被用于资源的建立或修改。
9.7 DELETE(删除)
DELETE方法请求源服务器删除请求URI指定的资源。此方法可能会在源服务器上被人为的干
涉(或经过其余方法)。客户端不能保证此操做能被执行,即便源服务器返回成功状态码。然而,
服务器不该该指明成功除非它打算删除资源或把此资源移到一个不可访问的位置。
若是响应里包含描述成功的实体,响应应该是200(OK);若是DELETE动做尚未执行,
应该以202(已接受)响应;若是DELETE请求方法已经执行但响应不包含实体,那么应该以
204(无内容)响应。
若是请求穿过缓存,而且请求URI(Request-URI)指定了一个或多个缓存当前实体,那么这
些缓存项应该被认为是旧的。DELETE方法的响应是不能被缓存的。
9.8 TRACE
TRACE方法被用于激发一个远程的,应用层的请求消息回路(译注:TRACE方法让客户端测
试到服务器的网络通路,回路的意思如发送一个请返回一个响应,这就是一个请求响应回
路,)。最后的接收者也许是源服务器,也许是接收到包含Max-Forwards头域值为0请求的代理
或网关。TRACE请求不能包含一个实体。
TRACE方法容许客户端去了解数据被请求链的另外一端接收的状况,而且利用那些数据信息去
测试或诊断。Via头域值(见14.45)有特殊的用途,由于它能够做为请求链的跟踪信息。利用
Max-Forwards头域容许客户端限制请求链的长度,这是很是有用的,由于能够利用此去测试代
理链在无限循环里转发消息。
若是请求是有效的,响应应该在实体主体里包含整个请求消息,而且响应应该包含一个
Content-Type头域值为”message/http”的头域。此方法的响应不能被缓存。
9.9 CONNECT(链接)
HTTP1.1 协议规范保留了CONNECT方法,此方法是为了能用于能动态切换到隧道的代理
((如 SSL tunneling [44]).)。
10.状态码定义
每个状态码在下面定义,包括此状态码依赖于方法的描述和响应里须要的任何元信息的描
述。
10.1 通知的 1xx
这类状态代码指明了一个临时性的响应,包含一个Status-Line和可选的头域,而且被一个空
行结束(译注:空行就是CRLF)。这类状态码响应没有必须的头域。由于HTTP/1.0没有定义
任何1xx状态码,因此服务器不能发送一个1xx响应给一个HTTP/1.1客户端,除了实验性的
目的。
客户端必须能在一个常规响应以前接受一个或多个1xx状态,即便客户端不指望100(继续)
状态响应。不被客户端指望的1xx状态响应可能会被用户代理忽略。
代理必须能转发1xx响应,除非代理和它的客户端的链接关闭了,或者除非代理本身响应请求
并产生1xx响应。(例如:若是代理添加了“Expect:100-continue”头域当转发请求时,那么它
没必要转发相应的100(继续)状态响应。)
10.1.1 100 继续 (Continue)
100状态响应告诉客户端应该继续请求。100响应是个中间响应,它被用于通知客户端请求的
初始部分已经被接收了而且此请求尚未被服务器丢弃。客户端应该继续发送请求的剩余部分,
或者,若是此请求已经完成了客户端会忽略此100响应。服务器在接收请求后必须发送一个终
结响应。见8.2.3节关于此状态码的讨论和使用。
10.1.2 101切换协议 (Switching Protocols)
服务器理解和愿意遵循客户端这样的请求,此请求经过Upgrade消息头域(见14.42节)指明
在链接上应用层协议的改变。 服务器将会切换到响应里Upgrade头域里指明的协议,它会以
一个空行结束此101响应。
只有协议切换时能受益协议才应该切换。例如,当传输资源时,切换到一个新的HTTP版本比
旧的版本要好,或者切换到一个实时的,同步的协议会带来好处时,这时咱们都应该考虑切换。
10.2 成功 2xx
这类状态码指明客户端的请球已经被服务器成功的接收,理解,而且接受了。
10.2.1 200 OK
此状态码指明客户端请求已经成功了。响应返回的信息依赖于请求里的方法,例如:
GET 请求资源的相应的实体已经包含在响应里并返回给客户端。
HEAD 相应于请求资源实体的实体头域已经被包含在无消息主体的响应里。
POST 响应里已经包含一个实体,此实体描述或者包含此POST动做执行的结果
TRACE 响应里包含一个实体,此实体包含终端对服务器接收的请求消息。
10.2.2 201 已建立(Created)
请求已经被服务器知足了而且已经产生了一个新的资源。新建立的资源的URI在响应的实体里
返回,可是此资源最精确的URI是在Location头域里给出的。响应应该含有一实体,此实体包
含此资源的特性和位置,用户或用户代理能从这些特性和位置里选择最合适的。实体格式被
Content-Type头域里媒体类型指定。源服务器必须能在返回201状态码以前创建资源。若是动
做(译注:这里指能建立资源的方法,如POST方法)不能被当即执行,那么服务器应该以
202(接受)响应代替。
一个201响应能够包含一个ETag响应头域,此头域的值指明了当前请求变量(译注:变量的
含义见第1.3节“变量”的解释)也即刚刚建立的资源的实体标签(entity tag)值,见14.19
节。
10.2.3 202 接受(Accepted)
请求已经被接受去处理,可是尚未处理完成。请求可能会或者不会处理完成,由于存在当处
理的过程当中拒绝处理的状况。
202响应是有意非担保性的。它是为了容许服务器能够为其它处理(如:天天执行一次的批处
理)接收请求而不须要用户代理在处理没有完成以前长期链接到服务器。响应里的实体应该包
含请求当前状态的声明而且应该包含一个状态监视指针或一些用户指望什么时候请求被知足的评估
值。
10.2.4 203 非权威信息(Non-Authoritative information)
此状态码响应指明响应里实体头域元信息不能从源服务器获而是从本地的或第三方响应副本里
收集的。这些元信息多是源服务器版本的子集或超集。如,包含一个存在本地的资源注释信息
就能够产生一个源服务器能理解的元信息的超集。利用此响应状态码不是必须可是比
200(Ok)响应却更加合适。
10.2.5 204 无内容 (No Content)
服务器已经知足了请求但并无返回一个实体而是返回更新的元信息。此响应可能包含新的或
更新的元信息以实体头域的形式,这些元信息应该相关于请求变量。
利用此204响应,客户端若是是一个用户代理,它就能够不用改变引发请求发送的文档视图
(译注:如一篇html文档在浏览器里呈现的样子)。204状态响应主要的目的是容许输入,而
没必要引发用户代理当前文档视图的改变,尽管一些新的或更新了的元信息可能会应用于用户代
理视图里的当前文档。
204响应不能包含一个消息主体,而且在头域后包含一个空行结束。
10.2.6 205 重置内容(Reset Content)
205状态响应是服务器告诉用户代理应该重置引发请求被发送的文档视图。此响应主要的目的
是清空文档视图表单里的输入框以便用户能输入其它信息。此响应不能包含一个实体。
10.2.7 206 部份内容(Partial Content)
服务器已经完成了客户端对资源的部分GET请求。请求必须包含一个Range头域(14.35节)
用来指出想要的范围,而且也有可能包含一个If-Range头域(见14.27节)来使请求成为一个
条件请求。
206状态的响应必须包含如下的头域:
- 或者含有一个Content-Range 头域,此头域指明了响应里的范围;或者含有一个值为
“multipart/byteranges”的Content-Type头域而且每部分包含Content-Range头域。若是一个
Content-Length头域出如今响应里,它的值必须是实际传输的消息主体的字节数。
- Date头域
- ETag 和/或 Content-Location头域,若是这些头域假设在相同请求的200响应里也会出现的
话。
- Expire,Cache-Control,和/或者Vary头域,若是这些头域的域值与之前同一变量响应中的
不同。
若是206响应是使用了强缓存验证(见13.3.3)的If-Range请求的结果,那么此响应不该该
包含其余的实体头域。若是响应是使用了弱缓存验证的If-Range请求的结果,那么响应必须不
能包含其余的实体头域;这能防止缓存里缓存的实体主体与更新头域之间的不一致性。另外,
响应必须包含假设在相同请求的200响应里的全部实体头域。
缓存不能把206响应和之前的缓存内容相合并若是ETag或Last-Modified头域并不能精确匹配,
见13.5.4。
一个不能支持Range和Content-Range头域的缓存不能缓存206(部分的)响应。
10.3 从新定向 3xx.
这类状态码指明用户代理须要更进一步的动做去完成请求。进一步的动做可能被用户代理自动
执行而不须要用户的交互,而且进一步动做请求的方法必须为GET或HEAD。一个客户端应该
发现无限的重定向循环,由于此循环能产生网络拥挤。
注意:之前此规范版本建议一个最多能有五个重定向。内容开发者应该知道客户端可能存在这
个限制。
10.3.1 300 多个选择.(Multiple Choices)
请求资源对应于众多表现形式中的一个,每一个表现形式都有一个特定的位置(location),而且代
理驱动协商(agent-driven negotiation)信息(见13章)被提供以便用户(或用户代理)能
选择一个更适的表现形式并重定向它的请求到那个表现形式的位置。
除非是HEAD请求,不然300状态响应应该包含一个实体,此实体包含一个资源特性和位置
列表,从这个列表里用户或用户代理能选择最合适的资源的表现形式。实体格式被Content-
Type头域里的媒体类型指定。用户代理选择最合适的表现形式的行为可能会被自动执行,这依
赖于实体格式和本身的能力。然而,此规范并无定义自动执行行为的标准。
若是服务器能肯定更好的表现形式,它应该为此表现形式在Location头域里包含一个特定的
URI来指明此表现形式的位置;用户代理可能会利用此Location头域自动重定向。300状态响
应是可缓存的除非被特别指明。
10.3.2 301 永久移动 (Moved Permanently)
请求资源被赋于一个新的永久的URI,而且任何未来对此资源的引用都会利用此301状态响应
返回的URI。具备连接编辑能力的客户端应该能自动把请求URI的引用转到到服务器返回的新
的引用下。此响应是能缓存的除非另外声明。
新的永久URI应该在响应中被Location头域给定。除非请求方法是HEAD,不然此响应应该包
含一个超文本提示和一个指向新URI的超文本连接。
若是客户端接收了一个来自非GET或HEAD请求方法的301响应,那么用户代理不能自动重
定向请求除非它能被用户确认,由于这可能会改变请求提交的条件。
注意:当客户端在接收了301 状态码响应后,会重定向POST 请求,一些已经存在的
HTTP/1.0用户代理会错误的把此请求变成一个GET请求。
10.3.3 302 发现(Found)
请求的资源暂时地存放在一个不一样的URI下。由于重定向的地址可能有时会被改变,客户端应
该继续为未来的请求利用请求URI(Request-URI)。302响应是只有在Cache-Control或Expires
头域指明的状况下才能被缓存。
临时的URI应该在Location头域里指定。除非请求方法是HEAD,不然此响应应该包含一个超
文本提示和一个指向新URI的超文本连接。
若是客户端接收了一个来自非GET或HEAD请求方法的302响应,那么用户代理不能自动重
定向请求除非它能被用户确认,由于这可能会改变请求提交的条件。
注意:RFC1945和RFC2068指定客户端不能在重定向请求的时候改变请求方法。然而,大多
数用户代理实现会把302响应当作是303响应,从而根据Location头域值的URI执行GET请
求,无论原始的请求方法是什么。303和307状态响应的目的是为使服务器明白客户端指望哪
种类型的重定向。
10.3.4 303 见其余(See Other)
请求的响应被放在一个不一样的URI下,而且应该用GET方法得到那个资源。此方法的存在主要
是让POST调用脚本的输出能使用户代理重定向到一个选择的资源。新的URI并非原始请求
资源的代替引用。303响应不能被缓存,可是再次重定向请求的响应应该被缓存。
不一样的URI应该在Location头域里指定。除非请求方法是HEAD,除非请求方法是HEAD,否
则此响应应该包含一个超文本提示和一个指向新URI的超文本连接。
注意:许多HTTP/1.1之前版本的用户代理不能理解303状态响应。当这些客户端比较关注于
互操做性的时候,302状态码应该被代替利用,由于大多用户代理对302响应的理解就是303
响应。
10.3.5 304 没有改变(Not Modified)
若是客户端已经执行了条件GET请求,而且访问服务器的资源是容许的,可是服务器上的文
档并无被改变,那么服务器应该以此状态码响应。304响应不能包含一个消息主体(messagebody),
而且在头域后面老是以一个空行结束。
此响应必须包含下面的头域:
- Date,除非14.18.1指明的那些规则下Date是能够遗漏的。若是时钟不许确的源服务器遵循
这些规则,而且代理和客户端在接收了一个没有Date头域的响应后加上了本身的Date(这在
RFC 2086里声明了,见14.19节),缓存将会正确操做。
- ETag 和/或 Content-Location头域,若是这些头域应在相同请求的200响应里出现的话。
- Expire,Cache-Control,和/或者Vary头域,若是这些头域值与之前同一变量响应中的不一
致。
若是条件GET请求使用强缓存验证(见13.3.3节)时,那么响应不该包含其它实体头域。当条
件GET使用弱缓存验证时,那么响应必须不能包含其它实体头域;这能防止缓存的实体主体
与更新的头域之间的不一致性。
若是一个304响应指示一个没有被缓存的实体,那么此缓存必须不用理会此响应,而且以无条
件请求重试请求。
若是缓存利用一个接收到的304响应去更新一个缓存项,那么缓存必须用此响应响应里任何最
新的域值更新缓存项。
10.3.6 305 使用代理 (Use Proxy)
请求资源必须能经过代理访问,代理的地址在响应的Location头域里指定。Location头域指定了
代理的URI。接收者被指望经过代理重试此请求,305响应必须被源服务器产生。
注意:RFC 2068并无说明305响应必须重定向一个单独请求而且只能被源服务器产生。不注
意这些限制会有重要的安全后果。
10.3.7 306没有使用的(unused)
306状态码被用于此规范之前的版本,是再也不使用的意思,而且此状态码被保留。
10.3.8 307临时重发(Temporary Redirect)
请求的资源临时存在于一个不一样的URI下。因为从新向可能有时会改变,因此客户端应该继续
利用此请求URI(Request-URI)为未来的请求。307响应只有被Cache-Control或Expire头域
指明时才能被缓存。
临时URI应该在响应的Location头域里给定。不然此响应应该包含一个超文本提示和一个指向
新URI的超文本连接,由于许多HTTP/1.1之前的用户代理不能理解307状态响应。所以,此
提示应该包含用户在新的URI上重试原始请求的必需信息。
若是307状态响应.对应的请求的方法不是GET或HEAD,那么用户代理不能自动重定向此请
求除非它能被用户确认,由于由于这可能会改变请求提交的条件。
10.4 客户端错误 4xx
状态码4xx类的目的是为了指明客户端出现错误的状况。除了当响应一个HEAD请求,服务器
应该包含一个实体,此实体包含一个此错误请求的解释。此状态码对全部请求方法都是适合的。
用户代理应该展现任何响应里包含的实体给用户。
若是客户端发送数据,利用TCP的服务器实现应该当心地确保客户端确认包含了响应的包
(packets)的接收,在服务器关闭此输入链接前。若是在关闭链接后,客户端继续发送数据给
服务器,那么服务器的TCP栈将发送一个重置包给客户端,这能擦除客户端非确认的输入缓
冲(input buffers)在这些缓冲被HTTP应用程序读和解析以前。
10.4.1 400 坏请求(Bad Request)
请求不能被服务器理解,因为错误的语法。客户端不该该在没有改变请求的状况下重试请求。
10.4.2 401 未受权的 (Unauthorized)
服务器须要对请求进行用户认证。响应必须包含一个WWW-Authenticate头域(见14.47),
此头域包含一个适用于请求资源的受权的激励(challenge)。客户端会以一个Authorization头
域重试请求。若是请求包含了受权证书,那么401响应指明对这些证书的受权失败。若是401响
应包含一个和之前响应的一样激励,而且用户代理已经尝试至少一次的受权,那么用户应该被
呈现包含在响应里的实体,由于这些实体可能包含相关的诊断信息。HTTP受权访问在“HTTP
Authentication:Basic and Digest Access Authentication”[43]里解释。
10.4.3 402 必需的支付 (Payment Required)
此状态码为未来的应用保留。
10.4.4 403 禁用 (Forbidden)
服务器理解此请求,但拒绝知足此请求。认证是没有做用的,而且请求不该该被重试。若是请求
方法是HEAD而且服务器想让客户端知道请求为何不能被知足,那么服务器起应该在响应实
体里描述此拒绝的缘由。若是服务器不但愿告诉客户端拒绝的缘由,那么404 状态码(Not
Found)响应将被使用。
10.4.5 404 没有找到(Not Found)
服务器并无找到任何能够匹配请求URI 的资源。没有迹象代表条件是暂时或永久的。
410(Gone)状态响应应该被使用,若是服务器经过内部配置机制知道一个旧资源永远不能获
得而且也没有转发地址。此状态码一般被使用,当服务器不但愿精确指出请求为什么被拒绝,或
者当没有任何其它响应可用时。
10.4.6 405 方法不被容许(Method Not Allowed)
此状态码表示请求行(Request-Line)里的方法对此资源来讲不被容许。响应必须包含一个
Allow头域,此头域包含以一系列对此请求资源有效的方法。
10.4.7 406 不可接受的 (Not Acceptable)
根据客户端请求的接受头域(译注:如:Accept, Accept-Charset, Accept-Encoding, 或者 Accept-
Language),服务器不能产生让客户端能够接受的响应。
除非是HEAD请求,不然响应应该包含一个实体,此实体应该包含一个可得的实体特性和位置
列表,经过它用户或用户代理能选择最合适本身的。实体格式被媒体类型指定。依赖于此格式和
用户代理的自己能力,选择最合适的可能会被自动执行。然而,此规范并无定义自动执行选
择的标准。
注意:HTTP/1.1服务器被准许根据请求里的接受头域会返回不可接受的响应。在一些状况下,
这可能更倾向于发送一个406响应。用户代理被鼓励观察到来的响应的头域来肯定此响应是不是
可接受的。
若是响应是不可接受的,用户代理应该暂时中止剩余数据的接收而且询问用户而后去决定进一
步的动做。
10.4.8 407 须要代理验证(Proxy Authentication Required)
此状态码和401(Unauthorized)类似,可是指示客户端首先必须利用代理对本身验证。代理必
须返回一个Proxy-Authenticate头域(见14.33节),此头域包含一个适用于代理的受权激励。
客户端可能利用一个合适的Proxy-Autorization头域去重试此请求(见14.34节)。HTTP访问授
权在“HTTP Authentication;Basic and Digest Access Authentication”[43]。
10.4.9 408 请求超时(Request Timeout)
客户端在服务器等待的时间里不能产生请求。客户端可能在之后会重试此请求。
10.4.10 409 冲突 (Confilict)
请求不能完成因为和当前资源的状态冲突。此状态码只被容许出如今指望用户也许能解决此冲
而且能从新提交此请求的状况下。响应主体应该包含足够的为用户认识此资源冲突的信息。理想
的状况下,响应实体应该包含足够为用户或用户代理解决此问题的信息;然而,这是也许没有
可能而且也没有必要。
冲突最可能发生在响应PUT请求的时候。例如,若是版本被使用而且被PUT的实体包含资源
的改变,而这些改变会和之前的(第三方的)请求的相冲突,那么服务器应该使用409响应去
指明它不能完成此请求。在这种状况下,此响应的实体可能包含这两个版本的差别点,响应的
实体格式以Content-Type头域指定。
10.4.11 410 不存在(gone)
请求资源在源服务器上再也不可得而且也没有转发地址可用。此条件被认为是永久的。具备连接编
辑能力的客户端应该在用户确认后删除请求URI的引用。若是服务器不知道或不容易去肯定条
件是不是永久的,那么此404(没有发现)状态响应将被代替利用。响应是可缓存的,除非另外
申明。
410响应主要的目的是为了web维护任务,这经过告诉接收者资源已经不可得了而且告诉接收
者服务器拥有者已经把那个资源的远程链接给移除了。对有时间限制的,推销性的服务,和对
再也不继续工做在服务器站点人员的资源,这个事件(410响应)是很是广泛的。它不须要把全部
长久不可得的资源标记为“gone”或者保持任意长时间—这须要服务器拥有者本身的判断
10.4.12 411 长度必需 (Length Required)
服务器拒绝接受请求里没有包含Content-Length头域的请求。客户端能够重试此请求若是它添
加了一个有效的Content-Length头域,此头域值指定了请求消息里消息主体的长度。
10.4.13 412 先决条件失败 (Precondition Failed)
在一个或多个请求头域里指定的先决条件当在服务器上测试为false时返回的响应。此响应容许
客户端把先决条件放放到当前资源的元信息(头域数据)之上,这样能防止请求方法被应用于
一个非目的性的资源。
10.4.14 413 请求实体太大
服务器拒绝处理请求由于请求实体太大以至达到服务器不肯意去处理。服务器可能关闭此链接
去防止客户端继续请求。
若是条件是暂时的,服务器应该包含一个Retry-After头域用来指明此条件是暂时的而且指明客
户端应该何时重试。
10.4.15 414 请求URI太长(Request-URI Too Long)
服务器拒绝为请求服务由于此请求URI太长了以致于服务器不能解析。这种状况是不多的,只
发生在当客户端把POST请求不合适地转换为带有大量查询信息的GET请求时。
10.4.16 415 不被支持的媒体类型(Unsupported Media Type)
服务器拒绝为请求服务,由于请求的实体的格式不能被此方法的请求资源所支持。
10.4.17 416 请求范围不知足 (Requested Range Not Satisfiable)
服务器返回一个此状态码的响应,若是请求包含一个Range请求头域(见14.35节),而且
此头域里range-specifier值没有和已选资源的当前extent值重叠,而且请求没有包含一个If-
Range请求头域。(对byte-ranges来讲,这意味着byte-range-spec的全部first-byte-pos
值大于选择的资源的当前长度)。
当此状态码响应是在byte-range请求返回时,响应应该包含一个Content-Range实体头域用
来指定已选资源的当前长度(见14.16节)。响应不能使用multipart/byteranges媒体类型。
10.4.18 417 指望失败(Expectation Failed)
Expect请求头域里指定的但愿不能被服务器知足,或者,若是服务器是代理,那么能肯定请
求不能被下一站(next-hop)服务器知足。
10.5 服务器错误 5xx (Server Error)
这类状态码指明服务器处理请求时产生错误或不能处理请求。除了HEAD请求,服务器应该包
含一个实体,此实体用来解释错误,和是不是暂时或长期条件。用户代理应该展现实体给用户。
此响应状态码能应用于任何请求方法。
10.5.1 500 服务器内部错误 (Internal Server Error)
服务器遇到了一个意外条件,此条件防止服务器知足此请求。
10.5.2 501 不能实现 (Not Implemented)
服务器没有能力去知足请求。当服务器不能识别请求方法而且不支持它请求资源的时候,这个
响应是很合适的。
10.5.3 502 坏网关 (Bad Gateway)
此响应说明:做为网关或代理的服务器从上游(upstream)服务器接收了一个无效的响应。
10.5.4 503 服务不能得到(Service Unavailable)
因为服务器暂时地过载或维护,服务器不能处理请求。这就是说这是暂时条件,此条件将会在
一些延时后被减轻。延迟的长度能够在Retry-After头域里指定。若是没有Retry-After被给,那
么客户端应该处理此响应就像它处理500响应同样。
注意:503状态码的存在并非意指服务器当产生过载时必须利用它。一些服务器可能但愿拒
绝此链接。
10.5.5 504 网关超时(Gateway Timeout)
做为网关或代理的服务器在不能及时地接收一个从URI指定的上游(upstream)服务器(例
如:HTTP,FTP,LDAP服务器)或者其余的辅助性服务器(例如:DNS服务器)的响应。
注意:当DNS查找超时时,一些部署的代理将会返回400或500响应。
10.5.6 505 HTTP版本不支持 (HTTP version Not Supported)
服务器不能支持,或拒绝支持此HTTP协议版本消息。505响应指明服务器不能或不肯意完成
这样的请求,这在3.1中描述了。此响应应该包含一个实体,此实体描述了为何此协议版本
不被支持和其余能被服务器支持的协议版本。
11.访问认证(Access Authentication)
HTTP提供一些可选的激励响应(challenge-response)认证(authentication)机制,这些机
制能被用于服务器去激励客户端请求,使客户端提供认证信息。经常使用访问认证框架,还有
“basic”和“digest”认证规范,都在“HTTP Authentication:basic and Digest Access
Authentication”[43]规范里指定。HTTP/1.1 规范采用了“激励(chanllenge)”和“证书
(credentials)”的定义。
12.内容协商 (Content Negotiation)
大多数响应包含一个实体,此实体包含人类用户能理解的信息。一般,但愿响应能提供给用户
相应请求的“最可得”(best available)的实体。对服务器和缓存来讲,不幸的是,并非所
有的用户都对这个“最可得”的实体有相同的喜爱,而且并非全部的用户代理(如web浏览
器)都能一致的呈现这些实体。因此,HTTP提供了几个“内容协商”的机制 — 当有多个可
得的表现形式的时候,对给定响应去选择最好的表现形式的过程。
注意:没有称作“格式协商”(译注:“格式”指的是“媒体类型”)的,这是由于选择的表
现形式可能会有相同的媒体类型,但却根据其它能力(capabilities),例如一种不一样的语言。
任何包含一个实体主体的响应应该由受协商来决定,包括错误响应。
在HTTP中,有两种类型的内容协商:服务器驱动协商和代理驱动协商。这两种类型的协商具
有正交性,所以能被单独使用或联合使用。一个联合使用的协商会被叫作透明协商,这发生在
当缓存利用源服务器提供的代理驱动协商信息为后续请求提供服务器驱动协商的时候。
12.1 服务器驱动协商(Server-driven Negotiation)
若是响应的最好的表现形式的选择是经过服务器上的算法来实现,那么这种方式的协商称作服
务器驱动协商。选择是基于响应可得的表现形式(根据不一样的维度,响应会不一样;例如,语言,
内容编码,等等)和请求消息里特定的头域或附属于请求的其余信息(如:网络客户端的地
址)。
服务器驱动协商是有优势的,当从可行的表现形式里进行选择的算法对用户代理来讲描述是比
较难的(译注:代理驱动协商),或者当服务器指望经过第一个响应发送“最好的猜想”
(“best guess”)给客户端时(若是“最好的猜想”对用户是合适的,能避免后续请求的回路
延迟)的时候。为了改善服务器的猜想,用户代理应该包含请求头域(Accept,Accept-
Language,Accept-Encoding,等等),这些头域能描述它对响应的喜爱。
服务驱动协商有以下缺点:
1. 对服务器来讲不可能确切地决定什么对用户来讲是最好的,由于那须要对用户代理和响应
目的的全面理解(如:用户到底想把响应展现到屏幕仍是打印到纸上?)。
2. 使用户代理在而每个请求里描述它的能力即不高效(假定只有少许的响应却拥有多个表
现形式)也潜在地侵犯用户的隐私。
3. 使源服务器的实现变得复杂,而且使为请求产生响应的算法实现变得复杂。
4. 可能会限制公有缓存(public cache)为多个客户请求利用相同响应的能力
HTTP/1.1包含下面的请求头域来使服务器驱动协商启动,这些请求头域描述了用户代理的能
力和用户喜爱:Accept(14.1 节),Accept-Charset(14.2 节),Accept-Encoding(14.3
节),Accept-Language(14.4节),和User-Agent(14.43节)。然而,一些源服务器并不
只局限于这些维度,这些服务器能基于请求的任何方面来让响应不一样,这些方面包括请求头域
以外的信息或在此规范里没有定义的扩展头域信息。
Vary头域能被用来表达服务器选择表现形式(representation)利用的参数,表现形式受服务
器驱动协商决定的。见14.44节描述了Vary头域如何被服务器的使用,13.6节描述了Vary头
域如何被缓存的使用。
12.2 代理驱动协商 (Agent-driven Negotiation)
对代理驱动协商来讲,在源服务器一个初始响应后,响应的最好表现形式的选择是被用户代理
执行的。选择是基于响应的一系列可得的表现形式,这些表现形式被包含在初始响应的头域或
初始响应的实体主体(entity-body)里,每一个表现形式被一个属于本身的URI指定。从这些表
现形式中选择可能被自动执行(若是用户代理有能力这样作)或者被用户从超文本链接菜单中
手工选择。
代理驱动协商是有优势的,当响应可能只能根据通常用途的维度(如:类型,语义,编码)而
不一样的时候,当源服务器不能经过查看请求而断定用户代理能力的时候,当共有缓存(public
cache)被用来分派服务器的承载和减小网络使用的时候。
代理驱动协商也须要第二次请求去得到最好表现形式的缺点。第二次请求只有当缓存被使用时
才是有效率的。另外,此规范没有定义用户代理自动选择表现形式的机制,虽然它也没有避免
这样的机制被做为一个扩展使用于HTTP/1.1。
HTTP/1.1定义了300(多个选择)和406(不接受的)状态响应来进行代理驱动协商,当服务
器不能或不肯意利用服务器驱动协商来提供一个不一样响应(a varying response)的是时候。
12.3 透明协商(Transparent Negotiation)
透明协商是服务器驱动协商和代理驱动协商的结合体。当一个缓存接收到服务器的响应,而且
响应里提供了一系列可得的表现形式(就像在代理驱动协商里的响应同样)而且缓存能理解维
度的差别,那么此缓存变得有能力表明源服务器为那个资源的后续请求去执行服务器驱动协商。
透明协商的优势在于它能分发源服务器的协商工做而且能移除代理驱动协商的第二次请求的延
迟,由于缓存能正确的猜想到合适的响应并返回给请求端。
此规范没有定义透明协商的机制,虽然它也没有避免任何这样的机制做为扩展被用于
HTTP/1.1。
13 HTTP中的缓存
HTTP一般应用于能经过采用缓存技术提升性能的分布式信息系统。HTTP/1.1协议包括的许多
使缓存尽量的工做的元素。由于这些元素与协议的其余方面有着千丝万缕的联系,并且他们
相互做用、影响,所以有必要分别从方法(methods),头(headers),响应状态码来介绍缓
存的基本设计。
若是缓存不能改善性能,他将一无用处。HTTP/1.1中缓存能够在许多状况下排除发送请求和发
送完整响应。前者减小了网络回路的数量;咱们利用一个“过时(expiration)”机制来为此目
的(见13.2节)。后者减小了网络应用的带宽;咱们用“验证(validation)”机制来为此目的
(见13.3)。
对行为,可行性,和关闭的操做的要求须要咱们能放松了语义透明性。HTTP/1.1协议容许服务
器,缓存,和客户端在必要的时候能显式地下降透明性。然而,由于不透明的操做能混淆非专
业的用户,同时可能和某个服务器应用程序不兼容(例如订购商品),所以协议透明性在下面
状况下才能被放松:
-- 当被客户端或源服务器放松时,只能被一个显式的协议层(protocol-level)请求放松
-- 当被缓存或被客户端放松时,只能在出现一个对终端用户的显式的警告时才能被放松
所以,HTTP/1.1协议提供这些重要的元素:
1.提供了彻底语义透明性(full semantic transparency)的特性当被通讯全部方须要时
2. 容许源服务器或用户代理显式地请求和控制非透明性操做的协议特性
3. 容许缓存给响应绑定警告信息(经过Warning头域来实现)的协议特性,当这些响应没有保
持语义透明的请求近似性(requested approximation)时
一个基本的原则是客户端必须可以发现任何语义透明性的潜在放松规则。
注意:服务器,缓存,或者客户端的实现者可能会面对设计上的决策,它并无明确地在此规
范里讨论。若是一个决策影响了语义透明性,那么实现者将会在维持语义透明性上犯错,除非
一个仔细且完整的分析能向咱们展现打破透明性带来的好处。
13.1.1 缓存正确性(Cache Correctness)
一个正确的缓存必须能用缓存里最新的(up-to-date)响应来响应请求(见13.2.5,13.2.6,
和13.12),已缓存的响应必须知足下面的条件:
1.已缓存的响应已被检测应与经过源服务器重验证后返回的响应等价。
2.已缓存的响应是足够保鲜(fresh)的(见13.2节)。缺省的状况下,这意味着此响应必须满
足客户端,源服务器,和缓存(见14.9节)的最少严格(least restrictive freshness)保
鲜要求;若是源服务器指定了保鲜要求,那么它是源服务器本身的保鲜要求。
若是一个已缓存的响应,因为客户端和源服务器的最多严格(most restrictive freshness)
保鲜要求,而不是足够保鲜的,那么在仔细考虑的状况下,缓存也许仍然会根据一个合适
的警告头域(见13.15和14.46)返回此已缓存的响应,除非这个响应不被容许(例如:通
过”no-store” cache-directive ,或者经过一个”no-cache” cache-request-directive;见
14.9节)。
3.已缓存的响应是一个合适的304(没有被改变),305(代理重定向),或 错误(4xx或
者5xx)响应消息。
若是缓存不能同源服务器通讯,若是已缓存的响应能正确的服务于请求,那么一个正确的缓存
应该用它缓存的响应去响应请求;若是不能服务器于此请求,那么缓存必须能返回一个错误或
一个警告指示通讯失败。
若是缓存从服务器端接收到一个响应(或者是一个完整的响应,或者一个304(没有改变)的
响应),此响应应该是服务器正常状况下发送到请求的客户端的响应,而且此响应并再也不新鲜,
那么此缓存应该把此响应转发给请求客户端而不须要添加一个新的Warning头域(而不须要移
去已经存在的Warning头域)。缓存并非简单的由于传输中响应变得陈旧而去尝试重验证响
应;这可能会致使一个无限的循环。用户代理接收一个陈旧的但没有Warning头域的响应,它
应该提示用户一个警告信息。
13.1.2 警告信息(Warnings)
不管什么时候,缓存返回一个响应,此响应既不是第一手的(first-hand)也不是足够保鲜(在13.1.1
节的条件2),那么缓存必须利用一个Warning经常使用头域来警告产生的影响。Warning头域和当
前定义的警告在14.46节里描述。这些警告容许客户端去采起合适的动做。
Warning头域可能被用于缓存相关的和其余的目的。使用Warning头域而不是错误状态码,区
别因而否是真正的错误。
警告被赋予三位数字警告码(warn-codes)。第一个数字指明:在一个成功的重验证以后,警
告是否必须或没必要从缓存项里删除。
1xx 警告描述了响应的保鲜或重验证状态,而且这些状态必须在一个成功重验证以后删除。1xx
警告码(warn-codes)多是由缓存产生的,当验证一个缓存项时。此警告码不能被客户端产
生。
2xx 警告描述了实体主体或实体头域的某些方面的信息,这些信息不能被重验证修改(例如,
一个实体主体的有损压缩),而且这些信息不能在成功重验证以后被删除。
见14.46节关于警告码的定义。
HTTP/1.0缓存将缓存全部响应中的警告,而且不会删除第一类警告。被要通往到HTTP/1.0缓
存的响应,存在其响应中的警告携带一个额外的warning-date域可防止未来的HTTP/1.1接收
端信任一错误的已缓存的警告。
警告一样携带一个警告文本。此文本多是任何合适的天然语义(可能基于客户端请求的
Accept头域),同时包含一个可选择的关于何种字符集被使用的声明。
多个警告可能会绑定一个响应(或者被源服务器发送或者被一个缓存发送),而且包括多个警
告能够共用一个警告码。例如,服务器可能会以英语和法语提供相同的警告。
当多个警告绑定一个响应时,有时候不可能把全部的警告都展现给客户。HTTP版本没有指定
严格优先规则去决定哪一个警告优先展现和以何种顺序去展现,可是能够探索一些方法。
13.1.3 缓存控制机制 (Cache-control Mechanism)
HTTP/1.1基本缓存机制(服务器指定过时时间和验证器)对缓存是隐式指令。某些状况下,服
务器或客户端可能须要给HTTP缓存提供显式指令。咱们利用Cache-Control头域为此目的。
Cache-Control头域容许客户端或服务器在请求或响应里传输多个指令。这些指令经常覆盖缺省
的缓存算法。做为一个经常使用规则,若是头域值中存在一个明显的冲突,那么最多严格解释
(most restrictive interpretation)的头域值会被应用(也就是说,能保留语义透明性的值)。
然而,一些状况下,cache-control 指令被显式地用来削弱语义透明性的近似性(例
如,”max-stale” 或者 “public”)。
Cache-control指令在14.9节被描述。
13.1.4 显式用户代理警告(Explicit User Agent Warnings)
不少用户代理容许用户覆盖基本缓存机制。例如,用户代理可能容许用户指定缓存实体(即便
实体明显是陈旧的)永远不要被验证。或者,用户代理可能习惯于给任何请求加上“Cache-
Control:max-stale=3600”。用户代理不该该缺省的执行非透明行为或致使非正常且无效率的缓
存行为,可是能够经过一个显式的用户动做,代理可能会被显式地设置去这样作。
若是用户已覆盖基本缓存机制,那么用户代理不管什么时候遇到不能知足服务器透明性要求
(server’s transparency requirements)的信息被展示时,用户代理应该显式地给用户以指示
(特别是,若是被展示实体被认为是陈旧的)。由于协议一般容许用户代理去断定响应是不是
陈旧,因此此指示只须要实际发生时才被展示。此指示没必要是对话框;它应该是一个图标(例
如,一个正在腐烂的鱼)或者一些其余的指示器。
若是用户以某种方式已覆盖缓存机制,同时这种方式可能非正常地下降了缓存效率,那么用户
代理应该继续指示此状态给用户(例如,经过一个图片显示)以便用户能谨慎地消费额外资源
或忍受额外延迟。
13.1.5 规则和警告的例外状况(Exceptions to the Rules and Warnings)
在某些状况下,缓存的操做者能够选择去设置返回陈旧的响应,即便此响应没有被客户端请求。
这个决定不该该被轻易决定,可是为了实用性或性能方面的要求可能会这样作,特别是当缓存
和源服务器链接很差时。无能什么时候当缓存会返回一个陈旧的响应时,缓存必须给此响应作个标
记(利用Warning头域),这样能使客户端软件能提醒用户可能会存在潜在的问题。
一样能够容许用户代理去采起步骤得到第一手的或保鲜的响应。因为这个缘由,若是客户端显
式地请求第一手的或保鲜的响应,缓存就不该该返回一个陈旧的响应,除非因为技术或策略方
面的缘由而不能遵照。
13.1.6 由客户控制的行为(Client-controlled Behavior)
当源服务器(退一步讲,能够是经过在响应里添加年龄的中间缓存)是过时信息的主要来源时,
在某些状况下,客户端可能须要控制缓存决定是否返回一个已缓存的响应而不须要经过服务器
验证它。客户端经过利用一些Cache-Control头域的指示命令(directives)来达到此目的。
客户端的请求可能会指定本身愿意接受一没有通过验证响应的最大年龄(age);指定0值会
强迫缓存重验证全部的响应。客户端一样也会指定在响应过时以前的最小保持时间。这两个选项
会加强对缓存行为的限制,所以不能进一步地放松缓存语义透明的近似性(approximation of
semantic transparency)。
客户端一样可能会指定它愿意接受(accept)到达的陈旧响应。这放松了对缓存的限制,同时
这可能违反了源服务器对语义透明性的限制,可是这能够支持脱机操做(disconnected
operation),或者高可用性(high availability)当链接很差时。
13.2 过时模型 (Expiration Model)
13.2.1 服务器指定过时(Server-Specified Expiratiion)
HTTP缓存会工做的很好,这是由于缓存能彻底地避免客户端对源服务器的请求。避免请求的
主要机制是使服务器经过提供一个未来的显式过时时间(explicit expiration time)以指示响应
能够知足后续的请求。也就是说,缓存能返回一个保鲜(fresh)的响应而不须要和源服务器接
触。
服务器能够给响应赋一个未来的显式过时时间(explicit expiration time),并确信在过时时间
以前实体不会改变。这一般能保持语义透明性,只要服务器对过时时间仔细斟酌。
过时机制只能应用于从缓存构建响应,而不能应用于当即转发给客户端的第一手(first-hand,
见1.3节术语)响应。
若是源服务器但愿强制语义透明的缓存去验证每一个请求,它给显式过时时间( explicit
expiration time)设为过去。这就是说响应老是陈旧的,因此当缓存利用此响应去服务于后续请
求时,缓存应该验证此响应。见14.9.4节,有更严格的方式来进行重验证。
若是源服务器但愿强迫任何HTTP/1.1缓存(无论此缓存是怎样设置的)去验证每个请求,
源服务器应该利用 “must-revalidate”缓存控制指令(见14.9节)。
服务器指定显式过时时间是经过利用Expires头域或Cache-Control头域里的max-age缓存控
制指令。
过时时间不能被用于强制客户代理去刷新显示或重载资源;过时的语义只能应用于缓存机制,
而且当对资源的发起新请求时,此机制只需检测此资源的过时状态。见13.13节,关于缓存和
历史机制的差别。
13.2.2 启发式过时
由于源服务器不能老是提供一个显式过时时间(explicit expiration time),HTTP缓存一般会
赋予一个启发式过时时间(heuristic expiration time),它采用一种算法,此算法利用其它头
域的值(例如Last-Modified时间)去估计一个合理的过时时间。HTTP/1.1规范没有提供特定
的算法,可是却增强了算法结果最坏状况的限制。由于启发式过时时间可能会损坏语义透明性,
他们应该被谨慎地使用,而且咱们鼓励源服务器尽量提供显式过时时间(explicit expiration
times)。
13.2.3 年龄(Age)计算
为了了解缓存项(译注:缓存项是用来响应请求的,它包含已缓存的响应实体)是不是保鲜的
(fresh),缓存须要知道其年龄是否已超过保鲜寿命(freshness lifetime)。咱们在13.2.4节
中讨论如何计算保鲜寿命,本节讨论如何计算响应或缓存项的年龄。
在讨论中,咱们利用术语“now”来表示“执行计算主机上时钟的当前值”。使用HTTP协议的
主机,特别是运行于源服务器和缓存的主机,应该使用NTP[28] 或其余相似协议来同步其时钟
到全球(globally)精确时间标准上。
HTTP1.1协议要求源服务器尽量在每一个响应里附加一个Date头域,而且赋予响应产生的时
间(见14.18节)。咱们利用术语“date_value”去表示Date头域的值,这是一种适合于运算操
做的表示方法。
当从缓存里获取响应消息时,HTTP/1.1利用Age响应头域来表达响应消息的估计年龄。Age响
应头域值是缓存对响应自从被源服务器产生或重验证到如今的时间估计值。
实际上,年龄的值是响应从源服务器途径每个缓存的逗留时间的总和,再加上响应在网络路
径上传输的时间。
咱们用“age_value”来表示Age头域的值,这是一种适于算术操做的表示方法。
一个响应的年龄(age)能够经过两种彻底独立的途径来计算::
1.now - date_value,若是本地时钟与源服务器时钟同步的至关好。若结果为负,则取零。
2.age_value,若是途径响应路径(response path)的全部缓存均遵循HTTP1.1协议。
若是咱们有两种不一样的方法计算响应的年龄,咱们能够合并两者以下:
corrected_received_age = max(now – date_value,age_value)
而且只要咱们有近似同步时钟或全HTTP/1.1(all-HTTP/1.1)路径,就能获得一个可信赖的
(保守的)结果。
因为网络附加延时,会在服务器产生响应与下一个缓存或客户端接收响应之间产生时间延迟。
若是不经修订,这一延迟会带来不正常的低年龄。
因为致使产生年龄值的请求是早于年龄值的产生,咱们能校订网络附加延迟经过记录请求产生
的时间。而后,当一个年龄值被接收后,它必须被解释成相对于请求产生的时间,而不是相对
响应接收的时间。无论有多少延迟,此算法会致使保守的结果。因此,咱们计算:
corrected_initial_age = corrected_received_age + (now - request_time)
这里“request_time”是请求的发送时间。
当缓存收到响应时,年龄计算的算法总结以下:
/*
* age_value
* is the value of Age: header received by the cache with this response.
* date_value
* is the value of the origin server's Date: header
* request_time
* is the (local) time when the cache made the request
* that resulted in this cached response
* response_time
* is the (local) time when the cache received the response
* now
* is the current (local) time
*/
apparent_age = max(0, response_time - date_value); //缓存收到响应时响应的年龄
corrected_received_age = max(apparent_age, age_value);
response_delay = response_time - request_time;
corrected_initial_age = corrected_received_age + response_delay;
resident_time = now - response_time; //即收到响应到如今的时间间隔
current_age = corrected_initial_age + resident_time;
缓存项(cache entry)的current_age是缓存项从被源服务器最后验证到如今的时间间隔(以
秒记)再加上corrected_initial_age。当从缓存项里产生一条响应时,缓存必须在响应里包含一
个Age头域,它的值应该等于此缓存项的current_age值。
Age头域出如今响应里说明响应不是第一手的(first-hand)(译注:第一手的说明,响应是直
接来自于源服务器到达接收端的,而不是来自于缓存里保存的副本)。然而相反的状况并不成
立,由于响应里缺乏Age头域并不能说明响应是第一手的(fisrt-hand),除非全部请求路径上的
缓存都遵循HTTP/1.1协议(也就是说,之前HTTP版本缓存没有定义Age头域)。
13.2.4 过时计算(Expiration Calculations)
为了肯定一条响应是保鲜的(fresh)仍是陈旧的(stale),咱们须要将其保鲜寿命
(freshness lifetime)和年龄(age)进行比较。年龄的计算见13.2.3节,本节讲解怎样计算保鲜
寿命,以及断定一个响应是否已通过期。在下面的讨论中,数值能够用任何适于算术操做的形
式表示。
咱们用术语“expires_value”来代表Expires头域的值。咱们用术语“max_age_value”来表示
Cache-Control头域里“max-age”控制指令的值(见14.9.3节)。
max-age指令优于Expires头域执行,因此若是max-age出如今响应里,那么定义以下:
freshness_lifetime = max_age_value
不然,若Expires头域出如今响应里,定义以下:
freshness_lifetime = expires_value - date_value
注意上述运算不受时钟偏差影响,由于全部信息均来自源服务器。
若是Expires, Cache-Control:max-age, 或 Cache-Control:s-maxage (见 14.9.3) 均
未在响应中出现,且响应没有包含对缓存的其余控制,那么缓存能够用启发式算法计算保鲜寿
命(freshness lifetime)。缓存必须对年龄大于24小时的响应附加113警告,若是此响应不带
这种警告。
一样,若是响应有最后修改时间(Last-Modified time),启发式过时值应不大于从那个时间开
始到如今这段时间间隔的某个分数。典型设置为间隔的10% 。
计算响应是否过时很是简单:
response_is_fresh = (freshness_lifetime > current_age)
13.2.5 澄清过时值(Disambiguation Expiration Values)
因为过时值容易被任意设置,有可能两个缓存包含同一资源的不一样保鲜值(fresh values)。
若是客户端执行获取请求接收到一个非第一手的响应,此请求响应在客户端缓存里仍然是保鲜
的,而且缓存项里的Date头域的值比新响应的Date头域值要新,那么客户端应该忽略此新响
应。若是这样的话,它能够以“Cache-Control:max-age=0”指令(见14.9节)重试请求,从而
去强制和源服务器重验证。
若是一个缓存对同一个表现形式(representation)拥有两个保鲜响应却有不一样的验证器,那么
缓存必须利用Date头域值最近的响应。这种状况可能发生因为缓存会缓存来自其它缓存的响应,
或者因为客户端已要求重载或重验证一个显然保鲜的缓存项的。
13.2.6 澄清多个响应(Disambiguating Multiple Response)
由于客户端可能收到经多个路径而来的响应,因此某些响应会通过一些缓存集,某些响应会经
过其它缓存集,客户端收到响应的顺序可能与源服务器发送响应的顺序不一样。咱们但愿客户端
利用最新的响应,即便旧响应仍然是保鲜的。
实体标签(entity tag)和过时值(expiration value)都不能决定响应的顺序,由于可能会出现
晚一点的响应故意携带过早的过时时间(expiration time)。日期值的精度被规定只有一秒。
当客户端尝试重验证一个缓存项的时,而且接收到的响应里Date头域晚于已存在的缓存项,
那么客户端应该无条件的重试请求,而且包含
Cache-Control: max-age=0
去强制任何中间缓存经过源服务器来验证(validate)它们的缓存副本,或者
Cache-Control: no-cache
去强制任何中间缓存去从源服务器得到一个新的副本。
13.3 验证模型(Validation Model)
当缓存拥有一个旧缓存项而且想利用它来做为客户端请求的响应时,缓存必须首先经过源服务
器(或者可能经过一个有保鲜响应的中间缓存)对其进行验证看是否此缓存项可用。咱们称作
“验证(validating)”此缓存项。咱们能够没必要花代价来重传完整响应(full response),并
且在缓存项无效时能够没必要产生额外的回路,所以HTTP1.1 协议支持使用条件方法
(conditional methods)。.
协议支持条件方法(conditional methods)的关键特征是围绕“缓存验证器(cache
validator)”展开的。当源服务器产生一个完整响应(full response)时,它同时会附加一些验
证器给响应,这些验证器和缓存项一块儿保存。当客户端(用户代理或缓存)对有缓存项的资源
执行条件请求时,客户端在请求里包含一个相关的验证器(validator)。
服务器(有多是源服务器或缓存服务器)核对请求里的验证器和当前此实体本地验证器是否
匹配,若是匹配(见13.3.3),则返回一个特定状态码(一般为304(没有改变))的响应并
不包含实体主体(entity body)。若是不匹配,服务器就返回完整响应(包含实体主体)。这样,
若是验证器匹配,咱们就避免了传输完整响应(full response);同时,若是验证器不匹配,
也避免了额外的回路。
在HTTP1.1协议中,一个条件请求和普通的请求类似,除条件请求携带一些特殊的头域(这
些头域包含验证器),包含这些特殊的头域就隐含地代表请求方法(一般是GET方法)为条
件请求方法。
协议中缓存验证条件有正向条件和负向条件。也就是说有存在验证器匹配,请求方法会执行;
验证器不匹配,请求方法也可能会执行。
注意:缺乏验证器的响应可能会被缓存,并且会被缓存用来为请求提供服务直到缓存副本过时,
除非用缓存控制指令显式地禁止缓存这样去作。然而,若是缓存没有实体的验证器,那么缓存
不能执行条件方法来获取资源,这就意味着在缓存副本过时以后不会获得刷新。
13.3.1 最后修改日期 (Last-Modified Dates)
Last-Modifed实体头域值常常被用做一个缓存验证器。简而言之,若是实体自从Last-Modifed
值以后没有改变,那么缓存项被认为是有效的。
13.3.2 实体标签缓存验证器(Entity Tag Cache Validators)
ETag响应头域值是实体标签,它提供了一个“晦涩(opaque)”缓存验证器。当在不方便保
存修改日期时,当在HTTP日期值的一秒精度不能知足须要时,或当源服务器但愿避免使用修
改日期产生的冲突时,经过实体标签能获得更可靠的验证,。
实体标签在3.11节描述了。使用了实体标签的头域在14.19,14.24,14.26和14.44节里描述
了。
13.3.3 强,弱验证器 (Weak and Strong Validators)
因为源服务器和缓存会比较两个验证器来肯定他们是否表明相同的实体,因此一般但愿实体发
生任何变化时验证器也相应变化,这样的验证器为强验证器。.
然而,可能存在这样的请求,服务器倾向于仅在实体发生重要的语义变化时才改变验证器,而
在实体的某些方面不发生重大改变时就不改变验证器。在资源变化时验证器未必变化的验证器
称为弱验证器.。
实体标签一般是强验证器,但协议提供一种机制来使实体标签变成弱验证器。能够认为强验证
器在实体的每一字节变化时而变化,而弱验证器仅在实体的语义变化时才变化。换言之,咱们
能认为强验证器是特定实体的标识,而弱验证器是同一类语义等价实体的标识。
注: 强验证器的例子:一个整数他会随着每次实体发生变化而递增。一个实体的修改时间,若是
以秒为精度,能被看做为弱验证器,由于在一秒内资源可能改变两次。对弱验证器的支持是可
选择的。然而,弱验证器容许更有效地缓存等价对象。
.
客户端产生请求并把验证器包含在一个验证头域(validating header fiield)里时或服务器比较
两个验证器的时候均用到验证器。强验证器可在任何状况下使用,而弱验证器仅在不依赖于严
格相等时才可用。当客户端产生条件GET请求来请求一个完整实体时,任何类型的验证器均可
以使用。然而,子范围(sub-range)请求时只能使用强验证器,不然客户端可能会获得一个不
一致的实体。
客户端能够在发出简单(非子范围)GET请求里既能够利用弱验证器也能够利用强验证器。客
户端不能利用弱验证器在其它的请求形式里。
HTTP1.1协议定义验证的惟一功能就是比较。有两种验证器比较方法,这依赖于比较的背景是
否容许利用弱验证器。
.
- 强比较方法:若是相等,两验证器必须彻底一致,而且两个验证器都是强验证器。.
- 弱比较方法:若是相等,两验证器必须彻底一致,但它们中的任何一个或所有被标明
“弱”(“weak”)的不会影响结果。
实体标签是强验证器除非它被显式地标记为弱(weak)的。3.11节给出了实体标签的语法。
最后修改时间(Last-Modifed头域的值)被用做请求的验证器时默认为弱验证器,除非知足下
列规则才断定它是强验证器:.
- 此验证器正在被源服务器用来和当前实体验证器进行比较,而且
- 源服务器知道相关的实体不会在当前验证器涵盖的秒内改变两次,
或者
- 此验证器即将被客户端用于If-Modified-Since 或者 If-Unmodified-Since头域里,由于客
户端有一个关于实体的缓存项,而且
- 缓存项包含一个日期值(Date value),日期值给出了源服务器发送源响应的时间,并

- Last-Modifed头域值至少提早于日期值(Date value)60秒。
或者
- 此验证器正在被中间缓存经过与其缓存项里保存的验证器相比较 ,而且
- 缓存项包含日期值(Date value),它指明了源服务器发送源响应(original response)
的时间,而且
- Last-Modifed头域值至少提早于日期值(Date value)60秒。
此种方法依赖于如下事实,若是两个不一样响应被源服务器在同一秒内被发出,但这两个响应都
有相同的最后修改时间(Last-Modified time),那么其中至少有一个响应的日期值和最后修改
时间的值(Last-Modifed的值)相等。60秒的限制能保证Date和Last-Modifed的值在不一样时
钟或在响应准备期间的不一样时刻产生。一个实现可能会利用大于60秒的值,若是它认为60秒
过短。
若是客户端但愿执行子范围(sub-range)请求来请求一个只有最后修改(Last-Modifed)时间但
没有晦涩(opaque)验证器时,它可能会认为只有最后修改(Last-Modified)时间是强的。
若缓存或源服务器接收到一条件请求,而不是完整响应GET请求时,他必须使用强比较方法
去计算条件。
此规定容许HTTP1.1,缓存和客户端能安全地执行子范围(sub-range)请求得到来自
HTTP/1.0得来的值。
13.3.4 关于什么时候使用实体标签和最后修改时间的规则
咱们对源服务器,客户端和缓存采用一套规则和建议来规定不一样的验证器什么时候被使用,出
于何种目的被使用。
HTTP/1.1 源服务器:
- 应发送一个实体标签验证器,除非产生此实体标签不可行。
- 能够发送弱实体标签来替代强实体标签,若是使用弱实体标签能提升性能或者不能发送
强实体标签。
- 应发送一Last-Modifed值若是能够的话,除非打破语义透明性(这可能因为利用此日期
于if-Modified-Since头域里)会致使严重的后果。
换句话说,对http1.1 源服务器来讲,比较好的作法是同时发送强实体标签和Last-Modified
值。.
为了合法,强实体标签必须随相关联的实体值改变而改变。弱实体标签应该随相关联的实体在
语义上发生改变而改变。
注意:为保证语义透明缓存,源服务器必须避免为两个不一样的实体重用某个特定的强实体标签
值,也不能重用某特定弱实体标签为两个语义不一样的实体。缓存项应该能保持任意长的时间,
而无论过时时间(expiraton time),因此不能假设缓存历来不会尝试利用之前得到的验证器
来验证缓存项。
HTTP/1.1 客户端:
- 若实体标签被源服务器提供,HTTP/1.1客户端必须在任何缓存条件请求(利用If-Match或
If-None-Match)里利用实体标签.。
- 仅Last-Modified值被源服务器提供时,HTTP/1.1客户端应在非子范围缓存条件请求(利
用If-Modified-Since)里利用此值。
- 仅Last-Modified值被HTTP/1.0源服务器提供时,HTTP/1.1客户端可能会在子范围缓存条
件请求(利用If-Unmodified-Since)里利用此值。
- 若是实体标签和Last-Modified值都被源服务器提供,HTTP/1.1客户端应该在缓存条件请
求里利用这两个验证器。这容许HTTP/1.0和HTTP/1.1缓存能合适地进行响应。
HTTP/1.1 源服务器,当接收到一个条件请求并同时包含Last-Modifed 日期(例如,在If-
Modified-Since,或If-Unmodified-Since 头域里)和一个或多个实体标签(例如在If-
Match,If-None-Match,或If-Range头域里)做为缓存验证器时,源服务器不能返回一个304
状态响应(没有改变)除非这样做能与请求里全部的条件头域一致。
HTTP/1.1缓存,当接收到一个条件请求而且此请求里同时包含Last-Modified日期和一个或多
个实体标签做为缓存验证器时,它不能返回一个本地已缓存的响应给客户端,除非已缓存的响
应与请求里全部条件头域一致。
注意:这些原理背后的规则是HTTP/1.1服务器和客户端应在请求和响应里尽量传输非冗余
的信息。接收这些信息的HTTP/1.1系统将会对这些接收到的验证器做最保守的假设。
HTTP/1.0客户端和缓存会忽略实体标签。一般,Last-Modified值会被这些系统接收和利用,以
提供透明性和高效缓存行为,所以HTTP/1.1源服务器这时应提供Last-Modified值。在一下很
少的状况,一个Last-Modified值做为验证器被HTTP/1.0系统使用时会带来严重的后果,这时
HTTP/1.1服务器不该提供一个Last-Modified值。
13.3.5 非验证条件(Non-validating Conditionls)
实体标签背后的原则是只有服务做者才知道资源的语义从而去选择一个合适的缓存验证机制,
而且任何比字节相等(byte-equality)比较方法复杂的验证器比较方法都会带来风险。因此,任
何其余的头域的比较(除了Last-Modified,为了兼容HTTP/1.0)历来不会被用于验证一个缓
存项。
13.4 响应的可缓存性(Response Cacheability)
除非被缓存控制(见14.9节)指令明确地限制,缓存系统能够将一成功响应做为缓存项,可
以返回缓存项里的响应副本而不须要验证它若是此副本是保鲜的,而且也能够在验证成功后返
回它。若是响应既没有缓存验证器也没有显式过时时间,咱们认为它不能被缓存,可是某些缓
存可能会违反这个约定(例如,当处于脱机时)。客户端能常常发现这种来自于缓存的响应,
只需经过把Date头域值同当前时间做比较。
注意:某些HTTP1.0缓存可能违反这一假设而没有提示任何警告。
然而,在一些状况下,缓存不适合保存实体,或使缓存的实体服务于后续请求。这可能由于服
务的做者认为绝对的语义透明性是有必要的,或着出于安全和隐私考虑。某些缓存控制指令因
此被提供是为了让服务器能指示某些资源实体,或部分实体,不能被缓存。
注意在14.8 节里描述了防止一个共享缓存(shared cache)去保存和返回一个之前包含
Authorization头域请求的响应。
除非缓存控制指令防止响应被缓存, 一个接收的响应若是它的状态码是
200,203,206,300,301或410,那么此响应应该被缓存保存并且可用于后续的请求,但
这必须受过时机制决定。然而,若是缓存不支持Range和Content-Range头域,那么它不能缓
存206响应(部份内容)响应。
缓存接收到的响应若是是其余的状态码(如,302和307),那么此响应不能被用于服务于后
续的请求,除非缓存控制指令或其余的头域显式地容许它能这样作。例如,这些头域包含下面
的头域: Expires 头域( 见14.21 ) ; “ max-age” , “ s-maxage” , “ mustrevalidate”,“
prox-revalidate”,“public”或“private”缓存控制指令(见14.9)。
13.5 从缓存里构造响应
缓存的目的是为了响应未来的请求而缓存请求的响应信息。在不少状况下,缓存简单地返回响
应的某部分给请求者。然而,若是缓存拥有一个基于之前响应的缓存项,它可能必须把新响应
的部分和它缓存项里的内容合起来。
13.5.1 End-to-end和Hop-by-hop头域
为定义缓存和非缓存代理的行为,咱们将HTTP头域分红两类:
- end-to-end头域,他们被传输给最终请求或响应的接收者。响应里end-to-end头域必需
做为缓存项的一部分存储,而且必须在任何缓存项构成响应里被传输。
- hop-by-hop头域,他们只对传输层链接有意义,而且即不能被缓存保存也不能被代理转
发。
下面的HTTP/1.1头域是hop-by-hop头域:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
全部其它被HTTP/1.1定义的头域均为end-to-end头域。
其它hop-by-hop头域必须在Connection头域(14.10 节)里列出,并将被引进于HTTP/1.1
(或后来的版本)里。
13.5.2 不可更改的头域 (Non-modifiable Headers)
HTTP1.1的某些特征,如数字认证(Digest Authentication),是基于某些end-to-end头域。
一个透明代理不该该改变end-to-end头域,除非这些头域的定义要求或容许这样作。
一个透明代理不能改变请求或响应里的下面头域,并且它不能添加这些头域到没有这些头域的
请求或响应里:
- Contents-location
- Content-MD5
- ETag
- Last-Modified
一个透明代理不能改变响应里的下面头域:
- Expires
但它能够添加这些头域若是响应里没有这些头域时。若是一个Expires头域被添加,它必须等于
响应里Date头域的值。
一个代理不能在包含no-transform缓存控制指令的消息中改变或添加下面的头域。
- Content-Encoding
- Content-Range
- Content-Type
一个非透明代理可能会在一个消息里改变或添加这些头域若是消息不包含no-transform缓存控
制指令,可是若是代理这样作了,它必须添加一个警告214(转换被应用)(见14.46节)。
注意:end-to-end头域的没必要要更改可能会致使认证失败,若是更强的认证机制被应用于后续
的HTTP版本中。此认证机制可能依赖于没有在此列举的头域值。
请求或响应里的Content-Length头域会根据4.4节的规则被添加或被删除。一个透明代理必须
保留实体主体的entity-length(见7.2.2),虽然它能够改变transfer-length(4.4节)。
13.5.3 联合头域(Combining Headers)
当一个缓存对服务器发出验证请求时,并且服务器提供304(没有改变)响应或206(部份内
容)响应时,那么缓存将构造一个响应发送给请求客户端。
若是状态码是304(没有改变),缓存利用缓存项里的实体主体(entity-body)做为客户端请
求响应的实体主体。若是响应状态码是206(部份内容)而且Etag或Last-Modified头域能精确
匹配,那么缓存可能把缓存项里的内容和接收到的响应里的新内容合并而且利用最后合并的结
果做为输出响应(见13.5.4)。
缓存项里的end-to-end头域被用于构造响应,除了:
- 任何保存的警告码是1xx(见14.46)的Warning头域必须从缓存项和转发的响应里删
除。
- 任何保存的警告码是2xx的Warning头域必需要在缓存项和转发的响应里保留。
- 任何304或206响应提供的end-to-end头域必须替换缓存项的相应头域
除非缓存决定去删除缓存项,不然它必须一样能用接收的响应里的相应end-to-end头域去替
换缓存项里的头域,除了上面描述的Warning头域。若是输入响应里的一个头域匹配缓存项里
多个头域,那么全部这些旧的头域必须被替换。
也就是说,输入响应的全部end-to-end头域会覆盖缓存项里全部相应的end-to-end头域(除
了缓存的警告码是1xx的Warning头域,它将会被删除即便没有被覆盖)。
注意:此规则容许源服务器去利用304(没有改变)或一个206(部份内容)响应去更新之前
同一实体或子范围实体响应的任何头域,虽然它也许不老是有意义或正确。这条规则不容许源
服务器去利用304(没有改变)或206(部份内容)响应去彻底地删除一个之前响应的头域。
13.5.4 联合字节范围(Combing Byte Ranges)
一条响应可能仅传送一个实体主体的某一部分,这是因为请求包含一个或多个Range指定的
范围,或者因为链接会被过早地断开。在几回这样得传输后,缓存可能已经接收了同一个实体
主体的多个范围部分。
若是缓存有一个实体的非空子范围,而且一个输入(incoming)响应(译注:输入响应是进入
缓存的响应,输出响应是从缓存出去的响应)携带了另外一子范围,那么缓存可能会把新的子范
围和已经存在的子范围联合起来若是下面二者同时知足:
- 输入响应和缓存项都有缓存验证器。
- 利用强比较方法使两个缓存验证器匹配(见13.3.3)。
若是任何要求不能知足,缓存必须利用最接近如今(most recent)的部分响应(基于任何响应
的Date头域值,而且会利用输入响应若是这些Date头域值相等或丢失了),并且必须丢弃其
它的部分信息。
13.6 缓存已协商响应(Caching Negotiated Responses)
使用服务器驱动内容协商(12.1节),会在响应里添加Vary头域,并改变缓存利用响应去服
务后续请求的条件和过程。见14.44节关于服务器利用Vary头域的描述。
服务器应利用Vary头域告诉缓存哪些请求头域被服务器用于从响应(可缓存的)对应的多个
表现形式里进行选择,响应由服务器驱动协商决定。Vary头域里指定的头域被称作选择请求头
域(selecting request-header)。
当缓存接收到一个后续请求,而且此请求的URI指定了一个或多个(包含一个Vary头域的)
缓存项时,缓存不能利用这个缓存项去构造响应从而服务于新的请求,除非全部出如今新请求
里的选择请求头域匹配来自于源请求里已被缓存保存的选择请求头域。
在两个请求里,咱们定义这两个选择请求头域匹配,若是而且只有第一个请求的选择请求头域
能被转换为第二个请求里的头域经过添加或删除线性空白(被容许出如今相应的BNF里的线
性空白)和/或把多个消息头域结合成一个头域经过4.2节里的规则。
一个Vary头域值是“*”老是不能匹配的,而且后续对那个资源的请求只能合适地被源服务器理
解。
若是缓存项里的选择请求头域(selecting request-header)不能匹配新请求的选择请求头域,
那么缓存不能利用缓存项去知足请求除非它能以条件请求把此新请求接力到源服务器而且源服
务器返回一个304(没有改变)的状态响应,并包含一个实体标签或一个指明被使用实体的
Content-Location头域。
若是一个缓存的表现形式已拥有实体标签,那么转发请求应是以条件请求发送而且应包含资源
对应的全部缓存项的实体标签于If-None-Match头域(不匹配则执行方法)里。这告诉了服务器
当前缓存拥有的实体集,以便若是实体集里的任何实体匹配请求的实体,那么服务器能利用
Etag头域于304(没有改变)响应里,从而去告诉缓存哪一个缓存项是合适的。若是新响应的实
体标签匹配已存在的缓存项,那么新响应应被利用去更新已经存在的缓存项的头域,并且更新
的最后结果必须返回给客户端。
若是任何已存的缓存项只包含相关实体的部份内容,那么它的实体标签不该被包含于If-None-
Match头域里,除非这个请求是范围请求而且缓存项能彻底知足请求。
若是缓存接收到一成功响应,响应的Content-Location头域匹配同一请求URI已存缓存项的
Content-Location头域,而且它的实体标签不一样于已存缓存项的实体标签,并且它的Date头
域值比已存缓存项更接近当前,那么已经存在的缓存项不能被返回去响应未来的请求而且将会
从缓存里删除。
13.7 共享和非共享缓存 (Shared and Non-Shared Caches)
出于安全和保密考虑,有必要区分共享和非共享缓存。非共享缓存是仅供一个用户访问,此情
况下,访问性(accessibility)应由适当的安全机制控制。全部其它缓存均被认为是共享的。此
协议的其它部分对共享缓存的操做添加限制以防止隐私丢失或访问控制的失败。
13.8 错误和不彻底的响应缓存行为
缓存收到不完整响应(例如响应的字节数比Content-Length头域指定的值要小)时也能够保
存,可是必须把此响应看做部分响应。部分相应能够合并(见13.5.4);合并结果多是完整
响应或还是部分响应。.缓存在没有显式标明响应是部分响应状况下(例如利用206(部份内
容)状态响应)不能把部分响应返回给客户端。缓存不能使用一个200(OK)状态码返回一个
部分响应。
若是缓存当试图重验证一个缓存项时收到一5xx响应,那么它既能够将此响应转发给请求的客
户端,或者执行跟服务器响应失败同样。在后面的状况下,它能够返回一个之前的接收的响应,
除非缓存项包含一个“must-revalidate”缓存控制指令(见14.9节)。
13.9 GET 和 HEAD 的反作用(Side Effects of GET and HEAD)
除非源服务器显式地禁止缓存它们的响应,不然缓存对任何资源的GET和HEAD方法不该有
致使错误的行为的反作用(side effects)若是这些响应来自于缓存。他们能够仍然有反作用,
但缓存在决定缓存时没必要考虑这些反作用。缓存老是被指望去观察一源服务器对缓存的显式限
制(explicit restrictions)。
咱们注意到此规则的一个例外:有些应用程序习惯于在在GETs 和HEADs 方法里使用查询
URLs(在rel_path_part里包含一个“?”)从而执行带来很大的反作用的操做,缓存不能把此
URIs的响应看做一个保鲜的,除非服务器提供一个显式过时时间(explicit expiration time)。
这就意味着,对这样的URIs的,来自HTTP/1.0服务器的响应不该被缓存保存。见9.1.1节相
关的信息。
13.10 在更新或删除后的无效性
在源服务器上,某些方法对某资源执行的影响,可能会引发一个或多个已存缓存项的非透明的
无效。也就是说,虽然他们可能会继续是保鲜的,可是他们不能准确的反应出源服务器对那个
资源的新请求的响应。
HTTP协议没法保证全部此类缓存项均被标明无效。例如,引发源服务器上资源变化的请求可
能不会穿过存有一个缓存项的代理。然而,却有一些规则帮助减小可能的错误行为。
在此节里,短语“使实体无效(invalidata an entity)”意味着缓存要么能够删除它保存的所
有的实体的实例,要么能够把这些实体实例标记为“无效”并在它们可做为后续请求的响应之
前进行重验证。
一些HTTP方法必须让缓存去使一个实体无效(invalidate an entity) 。这些实体要么被请求
URI指定,要么在Location或在Content-Location头域里被指定(若是出现的话)。这些方法
是:
- PUT
- DELETE
- POST
为了防止服务器攻击拒绝,一个基于Location或Content-Location头域里的URI的无效处理
必须只有在URI的host部分和请求URI里的host部分相同时才被执行。
一个缓存若是不能理解请求里的方法,那么它应该使请求URI指定的任何实体无效。
13.11 强制写经过( Write-Through Mandatory)
全部可能对源服务器资源进行修改的方法都要写经过(written through)给源服务器。这一般包
括全部除了GET和HEAD的方法。缓存在将此种请求转发给服务器并得到相应响应前不能对请
求客户端作出响应。 但这个不能阻碍代理缓存在服务器已发送最终响应(final replay)以前发
送100(继续)响应。
相反的状况(一般叫“写回”或“拷贝回”缓存)在HTTP1.1中是不容许的,这是因为保持
一致的更新是很是困难的,而且在写回以前也会存在服务器,缓存和网络故障的问题。
13.12 缓存替换 (Cache Replacement)
若是一个新可缓存(见14.9.2, 13.2.5, 13.2.6 和 13.8)响应从一资源被缓存接收,而且同一资
源的已存响应已经被缓存保存,那么缓存应该利用新响应去响应当前请求。缓存可能会把这一
新响应放进存储里,而且能够,若是它知足全部其它要求,利用此响应来响应任何未来的请求。
若是缓存想把此新响应加进缓存存储,13.5.3的规则必须应用。
说明:一个新响应若是其Date头域值比已存已缓存的响应的Date头域值要旧,那么它是不可
缓存的。
13.13 历史列表 (History Lists)
用户代理常用历史机制(history mechanisms),如“后退”按钮和历史列表,来从新展
示一个会话的先前实体。
历史机制和缓存机制是不一样的。特别是历史机制不该尝试给资源当前状态展现一语义透明视图。
其历史机制只是为了展现资源获取当时用户看到的东西。
默认状况,过时时间(expiration time)没有应用于历史机制(history mechanisms)。若是实
体仍然在存储里,历史机制应该对其显示即便其实体已通过期了,除非用户专门地设置代理去
刷新已过时的历史文档。
这不能防止历史机制告诉用户某视图可能过时。
注意:若是历史机制不必地阻止了用户查看陈旧资源,那么这会强制服务做者避免利用
HTTP过时控制和缓存控制当他们想利用时。服务做者能够认为用户不被呈现错误消息或警告
消息是很是重要的,当他们利用导向按钮(如回退按钮)去看之前得到的资源时。即便有时这
些资源本不该被缓存保存,或应很快过时,用户界面的考虑可能会强制服务做者去寻求其它防
止缓存的方法(例如,“一次性”URLs)为了不不正确的历史机制功能的影响。
14 头域定义
本节定义了全部HTTP/1.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 ) ]
星号”*”字符用于把媒体类型组合成一个范围,“*/*”指明了全部的媒体类型而“type/*”指明
type类型的全部子类型。Media-range可能包含一个媒体类型参数。
每个media-range可能会跟随一个或多个accept-params,以“q”参数指明一个相对的喜好
程度的质量因子。经过第一个“q”参数(若是有的话)把accept-params和media-range参数
分离。喜好程度质量因子容许用户或用户代理去指明对那个media-range 的相对喜好程度,
qvalue的范围是从0到1(见3.9节)。缺省是q=1。
注意:利用“q”参数名字将媒体类型参数(译注:media-range里的parameter)和acceptextension
分离开来是基于历史的实践。尽管这能防止任何以“q”命名的媒体类型参数应用于
media-range 里,但在一个media-range 里使用“q”被认为是不可能发生的,这是由于在
IANA的媒体类型注册表里是没有“q”参数的而且在Accept头域里利用媒体类型参数也是不多
见。未来的媒体类型不被鼓任何以“q”命名的参数注册。
例子::
Accept :audio/*;q=0.2 , audio/basic
该例应该被解释成“我喜欢audio/basic,可是能够给我发送任何audio类型若是它最容易获得,
但在喜好程度质量要降低80%”。
若是没有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/x-dvi也不存在,那么发送text/plain实体。”
Media-range能被更具备特殊性的media-range或媒体类型覆盖。若是多个media-range应用
了一个特指的类型,那么最具备特殊性的应该优先。例如:
Accept: text/*, text/html, text/html; level=1, */*
拥有下面的优先顺序:
1)text/html; level=1
2)text/html
3)text/*
4)*/*
一个媒体类型的喜好程度质量因子是和一个给定的媒体类型联系在一块儿的,它是由查找能最高
优先匹配那个媒体类型的media-range决定的。例如:
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
注意:一个用户代理可能会为一个特定的media-range提供一个缺省的质量值的集合。然而,
除非用户代理是一个不能和其余的呈现代理交互的封闭的系统,不然这个缺省的集合应该能够
被用户可设置的。
14.2 Accept-Charset
Accept-Charset 请求头域能够用来指名哪些字符集的响应对请求端是可接受的。Accept-
Charset头域使客户端能通知服务器产生哪些能让客户端更理解的字符集响应。
Accept-Charset = "Accept-Charset" ":"
1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
字符集值在3.4节里描述。每个字符集可能被给于一个相联系的质量值用来表示用户对那个
字符集的喜好程度。缺省值是q=1.例如:
Accept-Charset:: iso-8859-5, unicode-1-1;q=0.8
若是特殊值“*”出如今Accept-Charset头域里,那么将匹配任何Accept-Charset头域里没有
的字符集(包含ISO-8859-1)。若是Accept-Charset头域里没有出现“*”出现,那么全部没有
在Accept-Charset 头域里显式声明的字符集的质量值都为0,可是有个例外,那就是若是
ISO-8859-1没有被显式声明,那么它的质量值为1。
若是Accept-Charset头域没有出现,那么缺省状况是任何字符集会接受。若是Accept头域出
如今请求消息里,而且若是服务器不能发送请求端指望的字符集(Accept-Charset头域指定
的)的响应,那么服务器应发送一个406(不能接受的)错误状态响应,尽管发送一个不可接
受的响应也是容许的。
14.3 Accept-Encoding
Accept-Encoding请求头域和Accept头域类似,但Accept-Encoding是限定服务器返回给客户
端能够接受的内容编码(content-coding,见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
服务器判断一个内容编码(content-coding)是不是可接受的,是根据Accept-Encoding头域,
并利用下面的规则来决定:
1.若是一个内容编码(content-coding)在Accept-Encoding头域里出现,那么它是能够接
受的(acceptable),除非它的qvalue为0。(这在3.9节里定义,一个qvalue为0说明
是“不可接受的”)
2.若是“*”出如今Accept-Encoding头域里,那么它匹配任何没有出如今Accept-Encoding
头域里的可得内容编码。
3.若是多个内容编码是可接受的,那么qvalue为最高的且非0的内容编码是最喜欢的。
4.“identity”内容编码老是可接受的,除非qvalue 为0,或者Accept-Encoding 头域包含
“*;q=0”而且同时没有包含“identity”内容编码。若是Accept-Encoding头域值为空,那么
只有“identity”编码是可接受的。
若是Accept-Encoding头域在请求里出现,而且若是服务器不能发送一个Accept-Encoding头
域里指定的编码响应,那么服务器应该发送一个406(不接受的)错误的响应。
若是没有Accept-Encdong头域出如今请求消息里,服务器应该假设客户端将接受任何内容编
码。在这种状况下,若是“identity”是这些可得的内容编码中的一个,那么服务器应利用
“identity”内容编码,除非服务器有附加信息指明其它内容编码对客户端是有意义的。
注意:若是请求没有包含Accept-Encoding头域,而且若是“identity”内容编码是不可得,那
么一般能被HTTP/1.0客户端容易理解的内容编码(也就是说,“gzip”和“compress”)是更
喜好的;一些不能合适展现消息的老客户端会发送其它内容编码。服务器也许一样能以特定用
户代理或客户端的信息来作决定。
注意:大多数HTTP/1.0应用程序不能识别或遵循一个内容编码跟随一个qvalue。这意味着
qvalue可能不能工做,而且不能被容许和x-gzip或x-compress在一块儿。
14.4 Accept-Language
Accept-Language请求头域和Accept请求头域相似,可是它是限定服务器返回给客户端喜好
的天然语言。
Accept-Language = "Accept-Language" ":"
1#( language-range [ ";" "q" "=" qvalue ] )
language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
每一个language-range均被赋以一个质量值,它表明用户对此language-range里涵盖语言的喜
爱程度。质量值缺省为1,例如:
Accept-Language: da, en-gb;q=0.8, en;q=0.7
好像在说:“我更喜欢Danish,可是也能够接收British English和其余的English的类型的语
言。”一个language-range匹配一个语言标签若是它能精确和语言标签相等,或者它能精确匹
配标签前缀,标签前缀是语言标签里字符“-”以前的部分。特殊的“*”字符出如今Accept-
Language头域里,代表能匹配任何不在此头域里的语言标签。
注意:前缀匹配规则并非意味着:给语言标签赋值时,若是用户理解某一个标签,那么他同
样会理解全部以这个标签做为前缀的全部标签。这种状况下,前缀规则只是代表能够容许使用
前缀标签匹配。
语言标签的质量因子是Accept-Language头域里匹配此语言标签的language-range的质量值。
若是没有Accept-Language头域里language-range匹配的语言标签,那么此语言的质量因子
被赋予0。若是没有Accept-Language头域出如今请求里,那么服务器应该假设全部语言将是
请求端可接受的。若是一Accept-Language头域出如今请求里,那么全部质量因子大于0的语
言是可接受的。
若是发送一个和用户喜好的语言相反,这将在15.1.4里讨论。
因为各个用户的理解程度不同,建议客户端应用程序应让用户对语言的偏好进行选择。若是
客户不能进行选择,那么Accept-Language头域不能在请求里给出。
注意:当让用户做出选择时,用户可能不熟悉上述语言匹配的细节,因此应该提供合适的向导。
例如,用户可能会认为选择“en-gb”会提供任何类型的英语文档若是British English不可得。在
这种状况下,用户代理应该能建议用户添加一个“en”去获得最佳匹配行为。
14.5 Accept-Range
Accept-Range响应头域容许服务器向客户指明服务器对范围请求的接受度。
Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges
acceptable-ranges = 1#range-unit | "none"
源服务器若是接受字节范围请求(byte-range request)那么能够发送
Accept-Ranges: bytes
可是不是必须这样作。客户端在没有接收此头域时也能够产生字节范围请求(byte-range
request)。范围单位(range units)被定义在3.12节。
服务器若是不能接受任何类型的范围请求(range request),将会发送
Accept-Ranges:none
去劝告客户不要尝试范围请求(range request)。
14.6 Age
Age响应头域表示发送者对响应产生(或重验证)时刻后通过的时间的估计。一个已缓存的响
应是保鲜的(fresh)若是此响应的年龄没有超过它的保鲜寿命(freshness response)。Age
值怎样计算在13.2.3节里描述了。
Age = "Age" ":" age-value
age-value = delta-seconds
Age值是十进制非负整数,而且以秒为单位.。
若是缓存接收到一个Age值大于它所能表示的上限,或它的年龄计算出现溢出,那么它必须传
送Age头域的值为2147483648 (2^31)。一个包含缓存的HTTP/1.1服务器必须在来自于自
身缓存的响应里包含一个Age头域。缓存应利用一个至少31位的运算类型。
14.7 Allow
Allow实体头域中列出了被请求URI(Request-URI)指定的资源所支持的方法。此头域的目的
是严格地让接收端知道资源所适合的方法。在405(方法不被容许)响应中必须出现Allow头域。
Allow = "Allow" ":" #Method
使用示例:
Allow: GET, HEAD, PUT
这一头域不能阻止客户端使用其余方法。但在Allow头域域中给出的方法应被执行。Allow头域
里指定的方法是每次请求时被源服务器定义的方法。
Allow头域里能够和一PUT请求一块儿使用,而为了说明新的或改变的资源支持这些方法。服务
器不须要去支持这些方法,服务器应包含一个Allow头域在响应里而且给出实际支持的方法。
代理(proxy)不能改变Allow头域即便它没有理解此头域里指定的全部方法,由于用户代理可
能和源服务器通讯有其余的意图。
14.8 Authorization (受权)
用户代理每每但愿经过服务器给本身受权,用户代理这样作是经过在请求里包含一个
Authorization请求头域,可是一般在接收了一个401响应后就没有必要再让服务器给本身受权
了。Authorization头域由包含用户代理对请求资源域的受权信息的证书(credentials)组成。
Authorization = "Authorization" ":" credentials
HTTP访问受权在“HTTP Authenticatiion:Basic and Digest Access Authentication”[43]中描
述。若是一个请求被受权而且一个域(realm)被指定,那么这个证书应对此域里全部的其余请
求是有效的(假设在此受权模式自己不须要其它例如根据激发值或利用同步时钟而变化的证
书)。
当一个共享缓存(shared cache)(见13.7 节)接收一个请求,而且此请求包含一个
Authorization头域时,那么缓存不能返回此请求相应的响应来响应任何其它的请求,除非下面
指定的例外之一发生:
1.若是此响应包含“s-maxage”缓存控制指令,那么此缓存能够利用此响应来响应后续请求。
可是(若是指定的最大年龄过时了)代理缓存必须首先经过源服务器来重验证此响应,同
时利用新请求里的Authorization请求头域去让源服务器给新请求受权。(这是s-maxage
定义的行为)。若是响应包含“s-maxage=0”,那么代理在重利用此响应以前必须老是重验
证它。
2.若是此响应包含“must-revalidate”缓存控制指令,那么缓存能够利用此响应来响应后续请
求。可是若是此响应是陈旧的,那么全部缓存必须首先经过源服务器重验证那个响应,同时
利用新请求里的Authorization请求头域去让源服务器去给此新请求受权。
3.若是此响应包含“public”缓存控制指令,那么此响应能够用来响应任何后续的请求。
14.9 Cache-Control
Cache-Control经常使用头域被用于指定必须在请求/响应链上的被全部缓存机制遵照指令。这些指
令指定了防止缓存去干涉请求或响应的行为。这些指令常常覆盖缺省的缓存算法。缓存指令是单
方向的,由于请求中指令的存在并不意味着一样的指令必须在响应中出现。
请注意HTTP/1.0缓存可能没有实现Cache-Control,而且也没有实现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 ) ]
当指令不伴有1#field-name参数出现时,该指令适用于整个请求或响应。当一个指令伴有一个
1#field-name参数时,此指令仅应用于被命名的头域,而不能应用于请求或响应的其余部分。
这一机制支持可扩展性;HTTP协议未来的版本的实现能够经过将指令应用于HTTP/1.1中未
定义的头域。
缓存控制指令可分为以下几类:
- 对什么是可缓存的限制;这可能只由源服务器指定。
- 对什么能被缓存保存的限制;这可由源服务器或用户代理指定。
- 对基本过时机制的改进;这可能由源服务器或用户代理指定。
- 对缓存重验证及重载的控制;这可能仅由用户代理指定。
- 对实体传输的控制
- 缓存系统的扩展。
14.9.1 什么是可缓存的
缺省状况下,若请求方法、请求头域和响应状态码指明响应为可缓存的,则此响应就是能够缓
存的。13.4 节总结了可缓存性的这些缺省状况。下列缓存控制响应指令(Cache-Control
response deirctives)容许源服务器覆盖缺省的响应可缓存性:
public
指明响应可被任何缓存保存,即使该响应一般是不可缓存的或只在非共享缓存里是可缓存的。
(参见14.8节,关于Authorization头域的更多详述。)
private
指明响应消息的部分或全部部分是为一个用户准备的而且不得被共享缓存保存。能够使源服
务器能够声明响应的特定部分来针对某一用户而且对其余用户的请求是无效的。一个私有
(非共享)缓存能够缓存此响应。
注:词语“私有”的使用仅用来控制响应在何处可被缓存,而且不能保证消息内容的隐私。
no-cache
若是no-cache缓存控制指令没有指定一个field-name,那么一个缓存不能利用此响应在没
有经过源服务器对它进行成功重验证的状况下去知足后续的请求。这容许源服务器去防止响
应被缓存保存,即便此缓存已被设置能够返回陈旧响应给客户端。
若是no-cache缓存控制指令指定一个或多个field-name,那么缓存能够利用此响应去知足
后续的请求,但这要受限于对缓存的其它限制。然而,指定的filed-name必须不能在后续请
求的响应里被发送若是此响应没有在源服务器那里获得成功重验证。这容许源服务器能防止
缓存去重利用响应里的某些头域,但仍然容许缓存能保存响应剩余部分。
注意:大多数HTTP/1.0缓存将不能识别或遵循这个指令。
14.9.2 什么能被缓存保存
no-store
no-store缓存控制指令的目的在于防止不经意地释放或保留敏感信息(好比存放在备份磁
带的信息)。 no-store缓存控制指令应用于整个消息,而且能够在响应里或在请求里被发
送。若是在请求里被发送,缓存不能保存此请求或此请求响应的任何部分。若是在响应里被
发送,缓存不能保存此响应或保存此响应请求的任何部分。此缓存控制指令能应用于非共享
缓存和共享缓存。“不能保存”在这个背景里的意思是指缓存不能有意地把信息保存在非易
失性存储里,并且必须尽力去删除易失性存储上的信息当它转发完毕后。
即便当此指令在一个响应里时,用户也可能会显式地在缓存系统以外保存这个响应(例如
利用一个“另存为”对话框)的地方。历史缓冲(History buffers)(见13.13节)可能保
存这个响应做为它们正常操做的一个部分。
此指令的目的是为了知足某些用户声明的要求,还有就是为那些比较在乎经过访问缓存数
据结构而发生信息泄漏的做者提供方便。在一些状况下,利用此缓存控制指令可能会加强隐
私,可是咱们注意到它并非在任何状况下都是可信任的或都能充分地保护隐私的。特别是,
恶意的或被损坏的缓存可能不能识别到或遵循此指令,而且网络通讯也容易随时受到窃听。
14.9.3 对基本过时机制的改进
实体的过时时间可由源服务器利用“Expires”头域(参见14.21节)指定。 或者,也能够在响
应里利用max-age缓存控制指令指定。当max-age缓存控制指令出如今一个已缓存的响应里时,
若是此响应的当前年龄(current age,译注:见13.2.3节关于current age的定义)大于为那
个资源的一个新请求时max-age里给定的年龄值(以秒),那么这个已缓存的响应是陈旧的
(stale)。对在一个响应里应用max-age缓存控制指令意味着此响应是可缓存的(也就是说
“公有的”)除非出现其它更具限制性的缓存控制指令于响应里。
若响应同时含有Expires头域和max-age缓存控制指令,那么max-age缓存控制指令应该覆
盖Expires头域,即便Expires头域更具限制性。此规则容许源服务器能够为一给定响应来为一
HTTP/1.1(或更迟)缓存提供一个比一HTTP/1.0缓存更长的过时时间(expiration time)。这
个规则可能会颇有用,若是某个HTTP/1.0 缓存不恰当地计算了年龄(ages)或过时时间
(expiration times),可能因为不一样步的时钟。
许多HTTP/1.0缓存实现可能会把响应里小于或等于该响应里Date头域值的Expires头域值看
成与“no-cache”缓存控制响应指令等效。若是一个HTTP/1.1缓存接收到这样一个响应,而且
此响应没有包含一个Cache-Control头域,缓存应把此响应当作一个不可缓存的,这是为了保
持和HTTP/1.0服务器兼容。
注意:一个源服务器可能但愿把一个相对较新的HTTP缓存控制特性,例如“private”缓存控
制指令,用于一个存有不能理解此特性的旧的缓存的网络上。源服务器应该须要把新特性和响
应里值小于或等于Date值的Expires头域联合起来,这样以便防止旧缓存不恰当地保存此响
应。
s-maxage
若是一响应包含一s-maxage缓存控制指令,那么对于一共享缓存(不能对私有缓存)来
说,s-maxage指定的值将会覆盖max-age缓存控制指令或Expires头域。s-maxage缓存
控制指令照样意指proxy-revalidate缓存控制指令(见14.9.4节)的语义,也就是说,共
享缓存在没有经过源服务器首先重验证这个已陈旧的缓存项时不能利用它来响应后续的请
求。s-maxage缓存控制指令老是被私有缓存忽略。
注意:大多数不遵循此规范的老的缓存没有实现任何缓存控制指令。 一个源服务器若是但愿利
用一缓存控制指令去限制(但不能阻止)遵循HTTP/1.1的缓存去进行缓存处理,那么它可能
会采用max-age控制指令去覆盖Expires头域,而且它会认可HTTP/1.1之前版本的缓存不会
去观察max-age缓存控制指令。
其它缓存控制指令容许一个用户代理(user agent)去改变基本的过时机制。这些指令可能会被
指定在请求里:
max-age
代表客户端愿接受这样一个响应,此响应的年龄不大于客户端请求里max-age指定时间
(以秒为单位)。除非max-stale缓存控制指令也包含在请求里,不然客户端是不能接收一
个陈旧响应的。
min-fresh
代表客户端愿接受一个这样的响应,其保鲜寿命不小于响应当前年龄(current age,见
13.2.3节关于current_age的定义)与客户端请求里的min-fresh指定的时间之和(以秒为单
位)。也就是说,客户端想要一个响应至少在min-fresh指定的时间内是保鲜的。
max-stale
代表客户端愿接受已通过期的响应。 若客户端请求为max-age指定了一个值,则代表客户
端愿意接受过时时间不超过在max-stale里指定秒数的响应。若max-stale没有赋值,则客
户端愿接受任意年龄的陈旧响应。
因为max-stale缓存控制指令出如今请求里,或因为此缓存被设置成能覆盖响应的过时时间,
致使缓存返回了一个陈旧响应,那么缓存必须把一个Warning头域放进这个陈旧响应里,此
Warning头域里应该是110警告码(响应是陈旧的)。
一个缓存能够被设置为能够不须要验证就能够返回陈旧的响应,但这不该与任何关于缓存验证
(例如,一个“must-revalidate”缓存控制指令)的“必须”等级的要求相冲突。
若新请求与缓存项都包含一个“max-age”缓存控制指令,那么取两个值的小者来为此请求决定
缓存项的保鲜程度。
14.9.4 缓存重验证和加载控制( Cache Revalidation and Reload
Controls)
有时,用户代理可能但愿或出于须要,坚持要求某缓存经过源服务器去重验证其缓存项,或者
要求其缓存从源服务器那里从新加载其缓存项。End-to-end重验证也许是有必要的,若是缓存
或源服务器已太高估计已缓存的响应(cached response)的过时时间。End-to-end从新加载
多是必要的,若是缓存项因为某缘由已经变得陈旧了。
End-to-end 重验证可能被请求,当客户端没有本地缓存副本,此时咱们称之为“未指定的
end-to-end重验证(unspecified end-to-end revalidation)”,或者,当客户端存有本地缓存
副本,此时咱们称之为“指定的end-to-end重验证(specific end-to-end revalidation)”。
利用缓存控制请求指令,客户端能指定下面三种动做:
End-to-end reload (End-to-end从新加载)
请求包含“no-cache”缓存控制指令,或,为了兼容HTTP/1.0 客户端,“Pragma: nocache”
缓存控制指令。头域名不能被包含在请求的no-cache缓存控制指令里。服务器不能利
用一个缓存副原本响应这样一个请求。
Specific end-to-end revalidation(指定的end-to-end重验证)
请求包含一个“max-age=0”缓存控制指令,它强制每一个途径源服务器的缓存必须经过下一
缓存或服务器来重验证它所拥有的缓存项(若是有的话)。此初始请求包含一带有客户端当
前验证器的缓存验证条件。
Unspecified end-to-end revalidation(未指定的end-to-end重验证)
请求包含一个“max-age=0”缓存控制指令,它强制每一个途径源服务器的缓存必须经过下一
缓存或服务器来重验证它所拥有的缓存项(若是有的话)。此初始请求没有包含一缓存验证
条件;沿着路径上的第一个拥有此资源缓存项的缓存(若是有的话)在请求里包含一带有
其缓存当前验证器的缓存验证条件。
max-age
当一个中间缓存被一个max-age=0的缓存控制指令强迫去重验证它所拥有的缓存项,而且
客户端已经在请求里包含了其自己拥有的验证器,此验证器可能不一样于当前缓存项里保存
的验证器。在这种状况下,缓存应该在不影响语义透明性的状况下利用任一验证器去执行请
求。
然而,验证器的选择可能会影响性能。最好的办法对中间缓存来讲,就是当执行请求时利用
它本身的验证器。若是服务器以304(没有改变)回复,那么此缓存能返回一个它本身如今
已经验证了的副本给客户端同时以一200(OK)状态码。若是服务器以一新实体和一新缓
存验证器来回复请求,那么此中间缓存会把返回的验证器同客户端请求里的验证器做比较
并利用强比较方法。若是客户端的验证器和源服务器的相等,那么此中间缓存器只是简单的
返回304(没有改变)响应。不然,它返回一个新的实体而且状态码是200的响应。
若是一个请求包含一个no-cache缓存控制指令,那么它不该包含min-fresh,max-stale,
或max-age缓存控制指令。
only-if-cache
在一些状况下,例如糟糕的网络链接,一客户端可能但愿一缓存只返回缓存当前保存的响
应,而且不须要缓存经过源服务器对其缓存项进行从新加载或重验证。若是这样做,客户端
可能会包含一个only-if-cached缓存控制指令于请求里。若是缓存接收了这样的指令,那么
缓存应利用缓存项(但必须知足请求的其它方面的限制)去响应,或以504(网关超时)状
态码响应。然而,若是一组缓存做为一统一的具备良好内部链接性的系统来操做,那么这个
请求可能会转发到缓存组的内部。
must-revalidate
因为一个缓存可能被设置去忽略服务器指定的过时时间,而且又因为一个客户端请求可能
包含一个max-stale缓存控制指令(具备类似的做用),因此此协议一样包含一个让源服务
器强迫缓存项被重验证的机制。当must-revalidate缓存控制指令出如今已被缓存接收的响应
里时,那么此缓存不能利用此缓存项,若是在它变得陈旧而且没有经过源服务器对它进行
重验证的状况下,去响应一个后续的请求。(也就是说,缓存必须每次进行end-to-end重验
证,若是单独地基于源服务器的Expire或max-age值,已缓存的响应是陈旧的话)
must-revalidate缓存控制指令能够为某些协议特性提供可信赖性操做。在全部状况下,一个
HTTP/1.1缓存必须遵循must-revalidate缓存控制指令;特别地,若是此缓存不能直接和源
服务器通讯,那么它必须产生一个504(网关超时)响应。
服务器应发送must-revalidate缓存控制指令,若是而且只有在服务器对实体的验证请求失
败而致使不正确的操做时,例如一个不动声息的未执行的金融事务。接收端不能采起任何违
反此缓存控制指令的自动的行为,而且不能自动地提供一个被验证无效的实体副本若是此
副本经过源服务器重验证失败。
尽管这不被推荐,用户代理(user agent)若是在糟糕的网络链接限制下,可能会违反此缓
存控制指令,可是,若是这样的话,它必须显式地警告用户这是一个未验证的响应。警告必
须在每次未验证的访问时被提供,并且用户代理应须要用户显式地确认信息。
proxy-revalidate
proxy-revalidate缓存控制指令和must-revalidate缓存控制指令具备相同的语义,但它不能
应用于非共享(non-shared)的用户代理缓存。它能被用于一已被受权请求的响应,去容许
用户缓存能保存或者事后能返回此响应而不须要去重验证它(由于它已经被那个用户受权
了一次),可是服务于多个用户的代理仍然须要每次去重验证它(为了保证每一个用户已被
受权)。注意这样的受权响应一样须要public缓存控制指令,这是为了容许响应能彻底被缓
存。
14.9.5 No-Transform缓存控制指令
no-ransform
中间缓存(代理)的实现者们已发现转换某个实体主体的媒体类型转是颇有用的。一个非透
明代理可能,例如,会在不一样图像格式之间进行转换,这是为了节约空间或在低速的链接上
减小通讯流量。
然而,当这些转换应用于某些应用的实体主体时,会引起严重操做问题。好比,医学图象应
用程序,科学数据分析应用程序和利用end-to-end认证的应用程序都必须保证接收到的实
体主体与原实体主体每一bit都是一致的。
因此,若是消息包括了no-ransform缓存控制指令, 那么中间缓存或代理不能改变13.5.2
节中列出的受限于no-transform缓存控制指令的头域。这意味着缓存或代理不能改变由这些
头域指定的实体主体的任何方面(aspect),包括实体主体自己的值。
14.9.6 缓存控制扩展(Cache control Extendions)
Cache-Control头域能被扩展,可经过一个或多个cache-extension标记,每一个标记能够被赋
于一个值。信息扩展(这些扩展无须缓存行为的改变)能够不经改变其它缓存控制指令的语义
而被添加。行为扩展是经过现有缓存控制指令的基本行为的修饰来实现的。 新缓存控制指令与
标准缓存控制指令二者都被提供,这样,不理解新缓存控制指令的应用程序会缺省地采用标准
缓存控制指令规定的行为,而那些能理解新指令的应用程序会将其看作是修改了标准缓存控制
指令的要求。这样,缓存控制指令的扩展能够在无须改变基本协议的状况下就可以实现。
扩展机制依赖于一HTTP缓存,此缓存听从全部本地HTTP版本缓存定义的缓存控制指令,遵
从必定的扩展,而且会忽略全部它不能理解的缓存控制指令。
例如,考虑一个假设的名为“community”的新缓存响应控制指令,此指令被当作是对private
缓存控制指令的修饰。咱们定义此新缓存控制指令以代表:除共享缓存,任何被communit值
命名的社区成员共享的缓存也可缓存此响应。例如,若是一个源服务器但愿容许UCI社区里的
成员在他们共享缓存里能够使用一私有响应,那么此源服务器应该包含:
Cache-Control: private, commuity="UCI"
一个见到此头域的缓存将会正确执行,即便此缓存不能理解这个community缓存扩展,由于
缓存一样能看到而且能理解private缓存控制指令因此这样能致使缺省的安全行为。
不能识别的缓存控制指令必须被忽略;咱们认为不能被HTTP/1.1缓存识别的任一缓存控制指
令会和标准缓存控制指令(或者响应的缺省缓存能力)联合在一块儿这样缓存行为会保持最小正
确性即便缓存不理解此扩展。
14.10 Connection
Connection经常使用头域容许发送者指定某些专属于某特定链接的选项,而且Connection头域不
能被代理(proxy)在之后的链接中传送。
Connection头域遵循以下语法:
Connection = “Connection” “:” 1#(connection-token)
connection-token = token
HTTP/1.1 代理必须在转发消息以前解析Connection 头域而且,为此头域中每个
connection-token,从消息中删除任何与connection-token 里同名头域。 链接选项是由
Connection头域中出现connection-token而指明的,而不是由任何相应的附加头域,由于附
加头域能够不被发送若是对应的那个链接没有参数。
Connection头域里列出的消息头域不得包含end-to-end头域,例如Cache-Control头域。
HTTP/1.1定义了“close”链接选项,这是为了让发送者指明在完成响应后链接将被关闭。
例如
Connection:close
不管是出如今请求或响应的头域里都代表:在完成现有请求/响应后链接不该被视是“持续的
(persistent)”(参见8.1节)。
不支持持久链接的HTTP/1.1应用程序必须在每一消息中都加上“close”链接选项。
接收到含有Connection 头域的HTTP/1.0(或更低版本)消息的系统必需要为每个
connection-token去删除或忽略消息中与之同名的头域。这避免之前版本的HTTP/1.1代理错误
转发这些头域。
14.11 Content-Encoding
“Content-Encoding”实体头域是对媒体类型的修饰。当此头域出现时,其值代表对实体主体采
用了何种内容编码,从而能够知道采用何种解码机制以获取Content-Type头域中指出的媒体
类型。Content-Encoding头域主要目的是能够在不丢失下层媒体类型的标识下对文档进行压缩。
Content-Encoding = "Content - Encoding" ":" 1#content-coding
内容编码在3.5节里定义。下面是一个应用的例子:
Content-Encoding:gzip
内容编码(content-coding)是请求URI 指定实体的特性。一般,实体主体之内容编码
(content-coding)的方式存储,然而只有在此实体主体被呈现给用户以前才能被解码。然而,
非透明代理可能会把实体主体的内容编码(content-coding)改为接收端能理解的内容编码
(content-coding),除非“no-transform”缓存控制指令出如今消息里。
若是实体的内容编码不是“identity”,那么此响应必须包含一个Content-Encoding实体头域
(见14.11节)而且列出非dentity的内容编码。
若实体的内容编码(content-coding)是一不被源服务器接受的请求消息,则响应必须以415
状态码响应(不支持的媒体类型)。
若实体采用多种编码,则内容编码必须在Content-Encdoing头域里列出,并且还必须按他们
被编码的顺序列出。额外的关于编码参数的信息能够在其它实体头域里提供,这在此规范里没
有定义。
14.12 Content-Language
Content-Language实体头域描述了实体面向用户的天然语言。请注意,这不必定等同于实体主
体中用到的全部语言。
Content-Language = “Content-Language” “:” 1#language-tag
语言标签由3.10节定义。Content-Language头域的主要目的在于让用户根据本身喜好的语言
来识别和区分实体。这样,若是实体主体的内容是面向丹麦语言的用户,那么下面的头域是适
合的:
Content-Language: da
若未指明Content-Language头域,那么此内容缺省是对全部语言的用户都支持。这既可能意味
着发送者认为实体主体的内容与任意天然语言无关,也多是发送者不知道内容该针对哪一种语
言。
在Content-Language头域里能够为内容(content)列出多种语言。例如,同时用毛里土语和
英语呈现“Treaty of Waitangi”就能够用下面表示:
Content-Language: mi,en
然而,有多种语言呈现于实体中并不表明此实体必定是为多个国家语言的用户准备的。好比《初
学拉丁文》之类的语言启蒙教程,显然是针对英语用户的。这里,合适的Content-Language头
域里应只包括“en”。
Content-Language可应用于任意媒体类型(media type) -- 它不限于文本式的文档。
14.13 Content-Length
Content-Length实体头域用于指明发送给接收者实体主体(entity-bidy)的大小(以十进制的
字节数表示),或是在使用HEAD方法时,指明实体主体本应在GET方法时发送实体主体的
大小。
Content-Length = “Content-Length” “:” 1*DIGIT
示例:
Content-Length: 3495
除非被4.4 节里规定的规则禁止,不然应用程序应该利用此头域指明消息主体(messagebody)
的传输长度。
任何大于或等于0的Content-Length均为有效值。若是一个Content-Length没有在消息里给定,
4.4节描述了如何判断消息主体的长度。
请注意Content-Length头域的含义与MIME中的关于此头域的定义有很大的区别,MIME中,
它在content-type类型为“message/external-body”的消息里是可选的。在HTTP中,在消息被
传输以前,若是消息的长度能被肯定,那么消息里应该包含Content-Length头域,除非不被
4.4节里的规则容许。
14.14 Content-Location
Content-Location实体头域可用来为消息里的实体提供对应资源的位置,当此实体的访问位置
独立于请求URI时。一服务器应该为响应实体的变量(variant,译注:见1.3节 术语)提供一
个Content-Location头域;尤为是在资源有多个对应的实体时,而且这些实体拥有各自不一样的
位置,而且能够经过这些位置单独地访问到各个实体,这时服务器应该为一个特定的变量
(variant)提供一个Content-Location头域。
Content – Location = “Content-Location” “:” (absoluteURI | relativeURI)
Content-Location的值一样为实体定义了基URI(base URI)。
Content-Location的值并不能做为源请求URI(original requested URI)的替代物;它只能是
陈述了请求时相应于特定实体的资源位置。未来的请求也许会用Content-Location里的URI做
为请求URI,若是请求指望指定那个特定实体源。
若是一个实体含有一个Content-Location 头域,而且此头域里的URI 不一样于得到此实体的
URI,那么缓存不能认为此实体能被用于去响应基于那个Content-Location里URI的后续请求。
然而,Content-Location能被用于区分同一请求资源的多个实体,这在13.6节里描述了。
若Content-Location拥有的是相对URI(relative URI),则此相对URI(relative URI)是相
对于请求URI来解析的(Request-URI)。
PUT或POST请求中含有Content-Location头域是没有定义的;服务器可自由忽略它。
14.15 Content-MD5
Content-MD5实体头域,正如RFC1864[23]里定义的同样,提供实体主体(entity-body)的
MD5摘要(digest),为的是提供end-to-end消息完整性检测(MIC)。(注:一MIC有利于
检测实体主体传输过程当中的偶然性变更,但不必定能防范恶意攻击。)
Content-MD5 = "Content-MD5" ":" md5-digest
MD5-digest=< 由RFC 1864 定义的base64的128位MD5摘要>
Content-MD5头域可由源服务器或客户端产生,用做实体主体的完整性检验。只有源服务器或
客户端可生成Content-MD5头域;不得由代理和网关生成,不然会有悖于其做为端到端完整
性检验的价值。任何实体主体的接收者,包括代理和网关,均可以检查此头域里的摘要值与接
收到的实体主体的摘要值是否相符。
MD5摘要的计算基于实体主体的内容,包括任何已应用的内容编码(content-coding),但不
包括应用于消息主体的任何传输编码。若接收到的消息具备传输编码,那么传输编码必须在用
Content-MD5值与接收到的实体相检测以前被解除。
这样作的结果是:摘要的计算是基于实体主体(entity-body)的字节的,就像一条命令:若是
没有传输编码被应用,它们将会被发送。
HTTP 将RFC 1864拓宽到容许对MIME复合媒体类型(如multipart/*,message/rfc822)计算
摘要,但这并不改变如前所述的摘要计算方法。
有一些关于这个的后果。复合媒体类型(composite types)的实体主体可能包含许多bodypart,
每个body-part 都有它本身的MIME 和HTTP 头域(包括Content-MD5,Content-
Transfer-Encoding,和Content-Encoding 头域),若是一个body-part 有一个Content-
Transfer-Encoding或Content-Encoding头域,那么应该认为此body-part的内容已被应用此
编码,而且认为此body-part 被包含于Content-MD5 摘要里,就是说在应用编码以后。
Transfer-Encoding头域不被容许出如今body-part里。
不可在计算或核对摘要以前就将任何其它换行转换为CRLF:实际传输的文本中使用的换行必
须原封不动的参与摘要计算。
注:虽然HTTP的Content-MD5的定义和RFC 1864中关于MIME实体主体的彻底同样, 但
HTTP 实体主体在对Content-MD5 的应用上仍然有几处与MIME 实体主体有所区别。首先,
HTTP 不象MIME 会用Content-Transfer-Encoding 头域,而是会使用Transfer-Encoding 和
Content-Encoding头域。 其次,HTTP比MIME更多地使用二进制内容类型,因此这种状况要
注意用于计算摘要的字节顺序是由那个类型所定义的传输字节顺序(transmission byte
order)。最后,HTTP容许文本类传输时采用数种换行,而不仅是规范的使用CRLF的的标准
形式。
14.16 Content-Range
Content-Range实体头域与部分实体主体一块儿发送,用于指明部分实体主体在完整实体主体里
哪部分被采用。 范围的单位(Range unit)在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
除非没法或很难判断,此头域应指明完整实体主体的总长度。星号“*”表示生成响应时的
instance-length未知。
不像byte-ranges-specifier值(参见14.35.1节),byte-range-resp-spec必须只能指明一个范
围,而且必须包含首字节和尾字节的绝对位置。
一个带有byte-range-resp-spec 的byte-content-range-spec,若是它的last-byte-pos 值小于
first-byte-pos值,或它的instance-length值小于或等于它的last-byte-pos值,那么就说明是
无效的。收到无效的byte-content-range-spec将被忽略,而且任何随其传输的内容都将被忽略
响应时发送状态码416(请求的范围没法知足)的服务器应包含一个Content-Range头域,且
里面的byte-range-resp-spec的值为“*”。instance-length指定当前选定资源的长度。状态码为
206(部份内容)的响应不该该包含一个byte-range-resp-sepc为“*”的Content-Range头域。
假定实体共含1234字节,byte-content-range-spec值的例子以下:
. The first 500 bytes:
bytes 0-499/1234
. The second 500 bytes:
bytes 500-999/1234
. All except for the first 500 bytes:
bytes 500-1233/1234
. The last 500 bytes:
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报文包含多个范围时(好比,对多个无重叠范围请求的响应),它们会被看成多部分
类型的消息来传送。基于为此目的多部分媒体类型为“multipart/byteranges”,它在附录19.2
里介绍了。见19.6.3里关于兼容性的问题描述。
对单个范围请求的响应不能使用multipart/byteranges媒体类型。若对多个范围请求的响应结果
为一单个范围,那么能够以一个multipart/byteranges媒体类型发送而且此媒体类型里只有一
个部分(part)。一个客户端若是没法对multipart/byteranges消息解码,那么它不能在一请求
中请求多个字节范围。
当客户端在一请求中申请多个字节范围时,服务器应按他们在请求中出现顺序的范围返回他们
所指定的范围。
若服务器出于句法无效的缘由忽略了byte-range-spec,它应把请求里无效的Range头域视为
不存在。(正常状况下,这意味着返回一个包含完整实体的200响应。)
若是服务器接收到一请求,此请求包含一没法知足的Range 请求头域(也即,全部byterange-
spec 里的first-byte-pos 值大于当前选择资源的长度),那么它将返回一个416 响应
(请求的范围没法知足)(参见10.4.17节)。
注: 客户端对没法知足Range请求头域不能期望服务器必定返回416(请求的范围没法满
足)响应而非200(OK)的响应,由于不是全部服务器都能处理Range请求头域。
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语义同样。此头域值
是一个在3.3.1里描述的HTTP-date;它必须用RFC1123[8]里的date格式发送。
Date="Date"":"HTTP-date
举个例子
Date:Tue,15 Nov 1994 08:12:31GMT
源服务器在全部的响应中必须包括一个日期头域,除了下面这些状况:
1. 若是响应的状态代码是100(继续)或101(转换协议),那么响应根据服务器的须要可
以包含一个Date头域。
2. 若是响应状态代码表达了服务器的错误,如500(内部服务器错误)或503(难以得到的
服务),那么源服务器就不适合或不能去产生一个有效的日期。
3. 若是服务器没有时钟,不能提供合理的当前时间的近似值,这个响应不必包括Date头域,
但在这种状况下必须遵守 14.18.1节中的规则。
一个收到的消息若是没有Date头域的话就会被接收者加上一个,若是这条消息将要被接收者
缓存或者将要经过一须要日期的网关。一个没有时钟的HTTP实现不能在没有重验证响应时去
缓存(保存)此响应。一个HTTP 缓存,特别是一个共享缓存,应该使用一种机制,例如
NTP[28],让它的时钟与外界可靠的时钟保持同步。
客户端在包括实体主体(entity-body)的消息中应该包含一个Date 头域,例如在PUT 和
POST请求里,即时这样作是可选的。一个没有时钟的客户端不能在请求中发送Date头域。
一个Date头域中的HTTP-date不该该是一个消息产生时刻以后的日期和时间。它应该表示与
消息产生时的日期和时间的最近似值,除非没有办法产生一个合理的精确日期和时间。理论上
说,日期应该是在实体(entity)产生以前的那一刻,实际上,日期是在不影响其语义值的情
况下消息产生期间的任意时刻。
14.18.1 没有时钟的源服务器运做
一些源服务器实现可能没有可得时钟。一个没有可得时钟的源服务器不能给一个响应指定
Expires或Last-Modified头域值,除非经过一个具备可信赖时钟的系统或用户,把此值与此资
源联系在一块儿。能够给Expires赋予一值,此值在服务器的配置时间之时或以前将被视为过去。
(这容许响应提早过时而不须要为每一个资源保存单独的Expires值)。
14.19 ETag
Etag响应头域提供了请求对应变量(variant)的当前实体标签。与实体标签一块儿使用的头域在
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头域的任何expectation值,那么它必须以
合适的错误状态码响应。若是服务器不能知足任何expectation值,服务器必须以417(指望失
败)状态码响应,或者若是服务器知足请求时遇到其它问题,服务器必须发送4xx状态码。
本头域为未来的扩展被定义成一个扩展的语法。若服务器接收到的请求含有它不支持的
expectation-extension,那么它必须以417(指望失败)状态响应。
expectation值的比较对于未引用标记(unquoted token)(包括“100-contine”标记)是而言
是不区分大小写的,对引用字符串(quoted-string)的expectation-extension而言是区分大小
写的。
Expect机制是hop-by-hop的:即HTTP/1.1代理(proxy)必须返回417(指望失败)响应如
果它接收了一个它不能知足的expectation。 然而,Expect请求头域自己是end-to-end头域;
它必需要随请求一块儿转发。
许多旧版的HTTP/1.0和HTTP/1.1应用程序并不理解Expect头域。
参见8.2.3节中100(继续)状态的使用。
14.21 Expires
Expires实体头域(entity-header)给出了在什么时候以后响应即被视为陈旧的。一个陈旧的缓存项
不能被缓存(一个代理缓存或一个用户代理的缓存)返回给客户端,除非此缓存项被源服务器
(或者被一个拥有实体的保鲜副本的中间缓存)验证。见13.2节关于过时模型的进一步的讨论。
Expires头域的出现并不意味着资源在Expire指定时间时、以前或以后将会改变或不存在。
Expires头域里日期格式是绝对日期(absolute date)和时间,由3.3.1节中HTTP-date定义;
它必须是RFC1123里的日期格式:
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”的日期格式当作是过去
的时间(也就是说,“已通过期”)。
为了将响应标为“已通过期”,源服务器必须把Expires头域里的日期设为与Date头域值相
等。(参见13.2.4节里关于过时计算的规则。)
为标记响应为“永不过时”,源服务器必须把Expires头域里的日期设为晚于响应发送时间一
年左右。HTTP/1.1服务器不该发送超过未来一年的过时日期。
除非另外被Cache-Control头域(见14.9节)指明,不然若是存在Expires头域且头域里的日
期值为某响应(可能缺省是不可缓存的)未来时间,那么就代表此响应是可缓存的。
14.22 From
From请求头域,若是有的话,应该包含用户代理当前操做用户的email地址。这个地址应该是
机器可用的地址,这被RFC 822 [9]里的“mailbox”定义的同时也在RFC 1123 [8]里做了修订:
From = "From" ":" mailbox
例如:
From: webmaster@w3.org
From头域能够被用于记录日志和做为识别无效或不指望请求的来源。他不该该被用做访问保护
的不可靠方法。这个头域的解释是:此请求是表明所指定人执行,此人应该承担这个方法执行
的责任。特别的,机器人代理(robot agents)应该包含这个头域,这样此人应该对运行此机器
人代理程序负责,而且应该能被联系上若是在接收端出现问题的话。
此头域里的网络email地址是能够和发出请求的网络主机(host)不一样。例如,当一个请求被通
过一代理(proxy)时,源做者的地址应被使用。
客户端在没有用户的容许时是不该发出From头域的,由于它可能和用户的我的隐私或他们站
点的安全策略(security policy)相冲突。强烈建议在任何一请求以前,用户能取消,受权,和
修改这个头域的值。
14.23 Host
Host请求头域指明了请求资源的网络主机和端口号,这能够从用户或相关资源给定的源URI
得到(一般是一个HTTP URL,在3.2.2节描述)。Host头域值必须表明源服务器或网关(由
那个源URL指定)的命名权限(naming authority)。这容许源服务器或网关去区分有内在歧
义的URLS,例如,拥有一个IP地址对应有多个主机名服务器,它的根“/”URL。
Host = "Host" ":" host [ ":" port ] ; 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没有包含请求
服务的网络主机名,那么Host头域必须给一个空值。一个HTTP/1.1代理必须确保任何它转发
的请求消息里必须包含一个正确的Host 头域,用于指定代理请求服务。全部基于网络的
HTTP/1.1服务器必须响应400(坏请求)状态码,若是请求消息里缺乏Host头域。
见5.2和19.6.1.1节里有针对Host头域的其余要求。
14.24 If-Match
If-Match请求头域是用来让方法成为条件方法。若是一个客户端已经从一个资源得到一个或多
个实体(entity),那么它能够经过在If-Match头域里包含相应的实体标签(entity tag)来验
证明体是否就是服务器当前实体。实体标签(entity tag)在3.11节里定义。这个特性使更新缓
存信息只须要一个很小的事务开销。当更新请求时,它照样被用于防止对资源错误版本的不经
意修改。做为一种特殊状况,“*”匹配资源的当前任何实体。
If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
若是If-Match头域里任何一个实体标签假设与一个类似GET请求(没有If-Match头域)返回
响应里实体的实体标签相匹配,或者若是给出“*”而且请求资源的当前实体存在,那么服务器
能够执行请求方法就好像If-Match头域不存在同样。
服务器必须用强比较方法(见13.3.3)来比较If-Match里的实体标签(entity tag)。
若是没有一个实体标签匹配,或者给出了“*”但服务器上没有当前的实体,那么服务器不能执
行此请求的方法,而且返回412响应(先决条件失败)。这种行为是颇有用的,特别是在当客
户端但愿防止一更新方法(updating method)(例如PUT方法)去修改此客户端上次获取但
现已改变的资源时,
若是请求假设在没有If-Match头域的状况下致使了除2XX或412之外的其余状态码响应,那
么If-Match头域必须被接收端忽略。
“If-Match: *” 的含义是:此方法将被执行,若是源服务器(或缓存,极可能使用Vary机制,
见14.44节)选择的表现形式(representation)存在的话,可是若是此表现形式不存在,那
么此方法不能被执行。
若是一个请求想要更新一个资源(例如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请求头域被用来让方法成为条件方法:若是请求变量(variant)自今后头域
里指定的时间以后没有改变,那么服务器不该该返回实体;而是应该以304(没有改变)状态
码进行响应,同时返回的消息不须要消息主体(message-body)。
If-Modified-Since = "If-Modified-Since" ":" HTTP-date
一个例子是:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
若是一个GET请求方法含有If-Modified-Since头域但无Range头域,那么此方法请求的实体
只有请求里If-Modified-Since头域中指定日期以后被改变才能被服务器返回。决定这个算法包
括下列状况:
a)若是请求假设会致使除状态200以外的任何其它状态码,或者若是If-Modified-Since日
期是无效的,那么响应就和正常的GET请求的响应彻底同样。比服务器当前时间晚的日
期是无效的。
b)若是自从一个有效的If-Modified-Since日期以来,变量已经被修改了,那么服务器应该
返回一个响应同正常GET请求同样。
c)若是自从一个有效的If-Modified-Since日期以来,变量没有被修改,那么服务器应该返
回一个304(没有改变)响应。
这种特征的目的是以一个最小的事务开销来更新缓存信息。
注意:Range请求头域改变了If-Modified-Since的含义;详细信息见14.35。
注意:If-Modified-Since的时间是由服务器解析的,它的时钟可能和客户端的不一样步。
注意:当处理一个If-Modified-Since头域的时候,一些服务器使用精确的日期比较方法,
而不是小于(less-than)比较方法,来决定是否发送304(没有改变)响应。当为缓存验
证而发送一个If-Modified-Since头域的时候,为了获得最好的结果,客户端被建议尽可
能地去利用之前Last-Modified头域里被接收的日期字符串。
注意:若是客户端,对同一请求,在If-Modified-Since 头域中使用任意日期代替Last-
Modified头域里获得的日期,那么客户端应该知道这个日期应该能被服务器理解。因为客
户端和服务器之间时间编码的不一样,客户端应该考虑时钟不一样步和舍入的问题。若是在客
户端第一次请求时与后来请求里头域If-Modified-Since指定的日期之间,文档发生改变,
这就可能会出现竞争条件,还有,若是If-Modified-Since从客户端获得的日期没有获得
服务器时钟的矫正,就有可能出现时钟误差等问题的。客户端和服务器时间的误差最有可
能是因为网络的延迟形成的。
既有If-Modified-Since头域又有If-Match或If-Unmodified-Since头域的请求的结果在本规范没
有定义。
14.26 If-None-Match
If-None-Match头域被用于一个方法使之成为条件的。一个客户端若是拥有一个或多个从某资源
得到的实体,那么它能验证在这些实体中有不存在于服务器当前实体中的实体,这经过在IfNone-
Match头域里包含这些实体相关的实体标签(entity tag)来达到此目的。这个特性容许通
过一个最小事务开销来更新缓存信息。它一样被用于防止一个更新方法(如,PUT)不经意的
改变一个客户端认为不存在但事实却存在的资源。
做为特殊状况,头域值“*”匹配资源的任何当前实体。
If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
若是If-None-Match头域里的任何实体标签(entity tag)假设与一个类似的GET请求(假设
没有If-None-Match头域)返回实体的实体标签相匹配,或者,若是“*”被给出而且服务器关
于那个资源的任何当前实体存在,那么服务器不能执行此请求方法,除非资源的修改日期和请
求里If-Modified-Since头域(假设有的话)里提供的日期匹配失败(译注:匹配失败说明资源
改变了)。换言之,若是请求方法是GET或HEAD,那么服务器应以304(没有改变)来响应,
而且包含匹配实体的相关缓存头域(特别是Etag) 。对于全部其它方法,服务器必须以412
(先决条件失败)状态码响应。
13.3节说明了如何判断两实体标签是否匹配。弱比较方法只能用于GET或HEAD请求。
若是If-None-Match头域里没有实体标签匹配,那么服务器能够执行此请求方法就像If-None-
Match头域不存在同样,可是必须忽略请求里的任何If-Modified-Since头域。也就是说,若是
没有实体标签匹配 ,那么服务器不能返回304(没有改变)响应。
若是假设在没有If-None-Match头域存在的状况下,请求会致使除2xx及304状态码以外响应,
那么If-None-Match头域必须被忽略。(见13.3.4节关于假如同时存在If-Modified-Since和If-
None-Match头域时服务器的行为的讨论)
“If-None-Match: *”的意思是:若是被源服务器(或被缓存,可能利用Vary机制,见14.44
节)选择的表现形式(representation)存在的话,请求方法不能被执行,然而,若是表现形
式不存在的话,请求方法是能被执行的。这个特性能够防止在多个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-None-Match头域,还含有一个If-Match或If-Unmodified-Since头域的话,
此请求的指向结果在此规范里没有定义。
14.27 If-Range
若是客户端在其缓存中有一实体的部分副本,并但愿其整个缓存项是及时更新的,那么客户端
能够在一条件GET(conditional GET)(利用了If-Unmodified-Since和If-Match头域二者或
其中之一)请求里利用Range请求头域。然而,若是因为实体被改变而使条件失败,那么客户
端可能会发出第二次请求从而去得到整个当前实体主体(entity-body)。
If-Range头域容许客户端使第二次请求短路(short-circuit)。说的通俗一点,这意味着:若是
实体没有改变,发送我想要的部分;若是实体改变了,那就把整个新实体发过来。
If-Range = “if-Range” “:”( entity-tag | HTTP-date)
若客户端没有一实体标签(entity tag),但有一个最后修改日期(Last-Modified date),它
能够在If-Range头域里利用此日期。(服务器经过检查一两个字符便可区分合法HTTP-date与
任意形式的entity-tag。)If-Range头域只应该与一Range头域一块儿使用,而且必须被忽略若是
请求不包含一个Range头域或者若是服务器不支持子范围(sub-range)操做。
若是If-Range头域里给定的实体标签匹配服务器上当前实体的实体标签(entity tag),那么
服务器应该提供此实体的指定范围,并利用206(部份内容)响应。若是实体标签(entity
tag)不匹配,那么服务器应该返回整个实体,并利用200(ok)响应。
14.28 If-Unmodified-Since
If-Unmodified-Since请求头域被用于一个方法使之成为条件方法。若是请求资源自今后头域指
定时间开始以后没有改变,那么服务器应该执行此请求就像If-Unmodified-Since头域不存在一
样。
若是请求变量(variant,译注:见术语)在此头域指定时间后之后已经改变,那么服务器不能
执行此请求,而且必须返回412(前提条件失败)状态码。
If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-日期
此域的应用实例:
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实体头域(entity-header)指定了变量(variant)被源服务器所确信的最后修改
的日期和时间。
Last-Modified = “Last-Modified” “:” HTTP-date
应用示例以下:
Last-Modified : Tue, 15 Nov 1994 12:45:26 GMT
此头域的确切含义取决于源服务器的实现和源资源(original resource)的性质。 对文件而言,
它可能仅仅指示文件上次修改的时间。对于包含动态部分的实体而言,它多是组成其各个部
分中最后修改时间最近的那个部分。对数据库网关而言,它多是记录的最新修改时间戳。对虚
拟对象来讲,它多是最后内部状态改变的时间。
源服务器不能发送一个迟于消息产生时间的Last-Modified日期。假如资源最后修改日期可能指
示未来的某个时间,那么服务器应该用消息产生的时间替换那个日期。
源服务器得到实体Last-Modified值应尽可能靠近服务器产生响应的Date值。这容许接收者对实
体修改时间做出准确的估计,特别是若是实体的改变时间接近响应产生的时间。
HTTP/1.1服务器应该尽量地发送Last-Modified头域。
14.30 Location
Location响应头域被用于为了完成请求或识别一个新资源,使接收者能重定向于Location指明
的URI而不是请求URI。对于201(Created)响应而言,Location是请求创建新资源的位置。
对于3xx响应而言,Location应被指定服务器为自动重定向资源所喜好的URI。Location头域
值由一个绝对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
Max-Forwards值是十进制的整数,它指定了请求消息能够剩余转发的次数。
对于一个TRACE或OPTIONS请求,若是包含一个Max-Forwards头域,那么接收此请求的
代理或网关必须能在转发(forwarding)此请求以前检查和更新Max-Forwards头域值。若是接
收的值为0,那么接收者不能转发此请求;而是,它必须做为最后的接收者响应。若是接收的
Max-Forwards值比0大,那么此转发的消息必须包含一个更新了的Max-Forwards头域,更
新的值是在接收时的值上减去1。
对本规范定义的全部其它方法以及任何没有明确做为方法定义部分的扩展方法的请求里,Max-
Forwards头域可能会被忽略。
14.32 Pragma
Pragma经常使用头域被用于包含特定执行指令,这些指令可能被应用于请求/响应链中任何接收者。
从协议的观点来看,pragma指令指定的行为是可选的;然而,一些系统可能要求行为必须满
足指令的要求。
Pragma = “Pragma” “:” 1#pragma-directive
pragma-directive =”no-cache” | extension-pragma
extension-pragma =token [ “=” ( token | quoted-string) ]
当no-cache指令出如今请求消息中,应用程序应该转发(forward)此请求到源服务器,即便
它拥有此请求响应的缓存副本。pragma指令和no-cache缓存控制指令(见14.9)有相同的语
义,而且它是为同HTTP/1.0 向后兼容而被定义。当一个no-cache 请求发送给一个不遵循
HTTP/1.1的服务器时,客户端应该既包含pragma指令也包含no-cache缓存控制指令。
pragma指令必须能穿过代理和网关应用程序,无论对于那些应用程序有没有意义。由于这些指
令可能对请求/响应链上的全部接受者有用。不可能为一个特定的接收者定义一个pragma;然
而,任何对接收者不相关的pragma指令都应该被接收者忽略。
HTTP/1.1 缓存应该把“Pragma:no-cache”看成好像客户端发送了“cache-control:nocache”
。在HTTP中不会有新的pragma指令会被定义。
14.33 Proxy-Authenticate
Proxy-Authenticate 响应头域必须被包含在407 响应(代理受权)里。此头域值由一个
challenge和parameters组成,challenge指明了受权模式,而parameters应用于请求URI的
代理。
Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
关于HTTP访问受权过程的描述在“HTTP Authentication:Basic and Digest Access
Authentication”[43]中介绍了。不像WWW-Authenticate头域,Proxy-Authenticate头域只能应用
于当前链接,而且不该该传递给下游(downstrem)客户端。然而,一个中间代理可能须要从
请求下游客户端而得到它本身的证书(credentials),这在一些状况下就好像代理正在转发
Proxy-Authenticate头域同样。
14.34 Proxy-Authorization
Proxy-Authorization请求头域容许客户端让一代理能给客户端本身(或客户端的用户)受权。
Proxy-Authorization头域值由包含用户代理(为代理和/或请求资源域)的受权信息的证书组成。
Proxy-Authorization = “Proxy-Authorization” “:” credentials
HTTP访问受权过程在“HTTP Authentication: Basic and Digest Access Authentication”[43]中
描述。不像Authorization头域,Proxy-Authorization头域只能应用于下一个指望利用Proxy-
Authenticate头域受权的外向(outbound)代理。。
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为基准(译注:0表明第一个字节,1表明第二个字节)。
若是存在last-byte-pos值,那么它必定大于或等于那个byte-range-spec里的first-byte-pos,
不然byte-range-spec在句法上是非法的。接收者接收到包括一个或多个无效的byte-rangespec
值的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-bytepos
比实体主体的当前长度要小,或至少包括一个suffix-length 非零的 suffix-byte-rangespec,
那么byte-range-set是能够知足的,不然是不可知足的。若是byte-range-set不能知足,
那么服务器应该返回一个416响应(请求范围不能知足)。不然,服务器应该返回一个206响
应(部份内容)
byte-ranges-specifier(字节-范围-说明符)值的例子(假定实体主体的长度为10000):
-- 第一个500字节(字节偏移量0-499,包括0和499): bytes=0-499
-- 第二个500字节(字节偏移量500-999,包括500和999): bytes=500-999
-- 最后500字节(字节偏移量9500-9999,包括9500和9999): bytes=-500 或 bytes=9500-
-- 仅仅第一个和最后一个字节(字节0和9999): bytes=0-0,-1
-- 关于第二个500字节(字节偏移量500-999,包括500和999)的几种合法但不规范的叙述:
bytes=500-600,601-999
bytes=500-700,601-999
14.35.2 范围请求(Range Retrieval Requests)
使用条件或无条件GET方法能够请求实体的一个或多个字节范围,而不是整个实体,这利用
Range请求头域,请求返回的结果就是Range头域指示的请求资源实体的范围。
Range = "Range" ":" ranges-specifier
服务器能够忽略Range头域。然而,.HTTP/1.1源服务器和中间缓存应该尽量支持字节范围,
由于Range支持从部分失败传输中有效地恢复,而且支持从大的实体中有效地获取部份内容。
若是服务器支持Range头域,而且指定的范围或多个范围对实体来讲是适合的:
1. 若是在无条件GET请求里出现Range头域,那么这将会改变没有Range头域时的GET
请求返回的结果。换句话说,返回的状态码不是200(ok)而是206(部分响应)。
2. 若是在条件GET(请求里利用了If-Modified-Since和If-None-Match中任意一个或二者,
或者利用了If-Unmodified-Since和If-Match中的任意一个或二者)请求里出现Range头
域,那么这将改变返回的结果,若是GET请求假设在没有Range头域时被服务器成功响
应而且条件为真。但若是条件为假,它不会影响304(没有改变)响应被返回。
某些情形下,除了使用Range头域外,可能还要同时使用If-Range头域(见14.27节)。
若是支持范围请求的代理接收了一个范围请求,并转发(forward)请求到内向(inbound)服
务器,而且接收到了一个完整实体,那么它只应该返回给客户请求的范围。代理将接收的整个
响应存储到它的缓存里若是此响应知足缓存分配策略。
14.36 Referer
Referer请求头域容许客户端,为了让服务器受益,指定请求URI来源的资源URI。(Referer
头域的Referer本应该写成Referrer,出现了笔误)。Referer请求头域容许服务器为了我的兴
趣,记录日志,优化缓存等来产生回退连接列表。它照样容许服务器为维护而跟踪过期或写错
的连接。Referer头域不能被发送若是请求URI从一个没有自身URI的资源得到,例如用户从
键盘输入。
Referer = "Referer" ":" ( absoluteURI | relativeURI )
例如:
Referer: http://www.w3.org/hypertext/DataSources/Overview.html
若是Referer头域的域值是相对URI,那么它将被解析为相对于请求URI。URI不能包含一个片
段(fragment)。见15.1.3关于安全的考虑。
14.37 Retry-After
Retry-After响应头域能被用于一个503(服务不可得)响应,服务器用它来向请求端指明服务
不可得的时长。此头域可能被用于3xx(重定向)响应,服务器用它来(如web浏览器)指明
用户代理再次提交已重定向请求以前的最小等待时间。Retry-After头域值多是HTTP-date或
者也多是一个响应时间后的十进制整数秒。
Retry-After = “Retry-After” “:” ( HTTP-date | delta-seconds )
下面是它的两个例子
Retry-After: Fri,31 Dec 1999 23:59:59 GMT
Retry-After:120
在后一例子中,延迟时间是2分钟。
14.38 Server
Server响应头域包含了源服务器用于处理请求的软件信息。 此域可包含多个产品标记(3.8
节),以及鉴别服务器与其余重要子产品的注释。产品标记按它们的重要性来排列,并鉴别应
用程序。
Server = “Server”
例:
服务器:CERN/3.0 libwww/2.17
若响应是经过代理转发的,则代理程序不得修改Server响应头域。做为替代,它应该包含一个
Via头域(在14.45节里描述)。
注:揭示特定的软件版本可能会使服务器易于受到那些针对已知安全漏洞的软件的攻击。 建议
服务器实现者将此域做为可设置项。
14.39 TE
TE请求头域指明客户端能够接受哪些传输编码(transfer-coding)的响应,和是否愿意接受块
(chunked)传输编码响应的尾部(trailer)(译注:TE 头域和Accept-Encoding 头域与
Content-Encoding 头域很类似,但TE 应用于传输编码(transfer coding),而Content-
Encoding应用于内容编码(content coding,见3.5节))。 TE请求头域的值可能由包含关键
字“trailers” 和/或用逗号分隔的扩展传输编码名(扩展传输编码名可能会携带可选的接受参数
的列表)(在3.6节描述)组成。
TE = "TE" ":" #( t-codings )
t-codings = "trailers" | ( transfer-extension [ accept-params ] )
若是出现关键字“trailers”,那么它指明客户端愿意接受(chunked)传输编码响应的尾部
(trailer)。 此关键字为传输编码(transfer-coding)值而保留,但它自己不表明一种传输编码。
举例:
TE: deflate
TE:
TE: trailers, deflate;q=0.5
TE请求头域仅适用于当即链接。因此不管什么时候,只要在HTTP/1.1消息中存在TE头域,链接
头域(Connection header filed)(参见14.10节)中就必须指明。
经过TE头域,服务器能利用下述规则来测试传输编码(transfer-coding)是不是可被客户端
接受的:
1.块(chunked)传输编码老是能够接受的。若是在TE头域里出现关键字“trailers”,那么客
户端指明它愿意表明本身或任意下游(downstream)客户端去接受块(chunked)传输编
码响应里的尾部(trailer)。这意味着,若是“trailers”给定,客户端正在声明全部下游
(downstream)客户端愿意接收块(chunked)传输编码响应里的尾部(trailer),或声
明它愿意表明下游接收端去尝试缓存响应。
注意:HTTP/1.1并无定义任何方法去限制块传输编码响应的大小,这是为了方便客户端
能缓存整个响应。
2.只要是出如今TE 头域里的传输编码都是可被请求端接受的,除非此传输编码跟随的
qvalue 值为0(根据3.9 节中定义,qvalue 为0 代表是“不可接受的”(not
acceptable)))
3.若是在TE头域里有指明多个传输编码是可接受的,那么传输编码(transfer-coding)的
qvalue值最大的是最容易被被接受的。块传输编码的qvalue值为1。
若是TE头域值是空的或者TE头域没有出如今消息里,那么服务器只能认为块(chunked)传
输编码的响应是请求端能够接受的。没有传输编码的消息老是可接受的。
14.40 Trailer
Trailer经常使用头域值指明了以块(chunked)传输编码的消息里尾部(trailer)用到的头域。
Trailer = "Trailer" ":" 1#field-name
一个HTTP/1.1消息会包含一个Trailer头域,若是消息利用了块(chunked)传输编码而且编
码里的尾部(trailer)不为空。这样作是为了使接收端知道块(chunked)传输编码响应消息尾
部(trailer)有哪些头域。
若是具备块传输编码的消息,但没有Trailer头域存在,则此消息的尾部(trailer)将不能包括
任何头域。3.6.1节展现了块传输编码的尾部(trailer)的利用限制。
Trailer头域中指示的消息头域不能包括下面的头域:
.Transfer-Encoding
.Content-Length
.Trailer
14.41 Transfer-Encoding
传输译码(Transfer-Encoding)经常使用头域指示了消息主体(message body)的编码转换,这
是为了实如今接收端和发送端之间的安全数据传输。它不一样于内容编码(content-coding),传
输代码是消息的属性,而不是实体(entity)的属性。
Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
传输编码(transfer-coding)在3.6节中被定义了。一个例子是:
Transfer-Encoding: chunked
若是一个实体应用了多种传输编码,传输编码(transfer-coding)必须以应用的顺序列出。传输
编码(transfer-coding)可能会提供编码参数(译注:看传输编码的定义,3.6节),这些编码
参数额外的信息可能会被其它实体头域(entity-header)提供,但这并无在规范里定义。
许多老的HTTP/1.1应用程序不能理解传输译码(Transfer-Encoding)头域。
14.42 Upgrade
Upgrade经常使用头域容许客户端指定它所支持的附加通讯协议,而且可能会使用若是服务器以为
能够进行协议切换。服务器必须利用Upgrade头域于一个101(切换协议)响应里,用来指明
哪一个协议被切换了。
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头域只能应用于应用程序层(application –layer)协议之间的切换,应用程序层协议
在传输层(transport-layer)链接之上。Upgrade头域并不意味着协议必定要改变;而且服务器
接受和使用是可选的。在协议改变后应用程序层(apllication-layer)的通讯能力和性质,彻底
依赖于新协议的选择,尽管在改变协议后的第一个动做必须是对初始HTTP 请求(包含
Upgrade头域)的响应。
Upgrade头域只能应用于当即链接(immediate connection)。所以,upgrade关键字必须被提
供在Connection头域里(见14.10节),只要Upgrade头域呈如今HTTP/1.1消息里。
Upgrade头域不能被用来指定切换到一个不一样链接的协议。为这个目的,使用301,302,303
重定向响应更合适。
这个规范定义了本协议的名字为“HTTP”,它在3.1节的HTTP版本规则中定义的超文本传输
协议家族中被使用。任何一个标记均可被用来作协议名字,然而,只有当客户端和服务器认为
这个名字对应同一协议才有用。
14.43 User-Agent
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响应头域值指定了一些请求头域,所有去决定某缓存是否被容许去利用此响应(而且此响
应仍然保鲜)去回复后续请求而不须要重验证(revalidation)。对于不可缓存或已陈旧的响应,
Vary头域值用于告诉用户代理(user agent)选择表现形式(reprentation)的标准。一个Vary
头域值是“*”意味着缓存不能根据后续请求的请求头域来决定此响应是合适的表现形式。见
13.6节关于缓存如何利用Vary头域。
Vary = "Vary" ":" ( "*" | 1#field-name )
一个HTTP/1.1的服务器应该包含一个Vary头域于任何可缓存的受限于服务器驱动协商的响应
里。这样作是容许缓存恰当去理解关于那个资源的未来请求,并通知用户代理关于那个资源的
协商出现。一个服务器可能包含一个Vary头域于一个不可缓存的受限于服务器驱动协商的响应
里,由于这样作可能为用户代理提供有用的关于响应变化的维度的信息。
一个Vary头域值由域名(filed-name)组成,响应的表现形式是基于Vary头域里列举的请求
头域来选择的。一个缓存可能会假设为未来请求进行相同的选择,若是Vary头域例举了相同的
域名,但必须是此响应在此期间是保鲜的。
Vary头域里的域名并非局限于本规范里定义的标准请求头域。域名是大小写不敏感的。
Vary域值为“*”指明不受限于请求头域的非特指参数(例如,客户端的网络地址)做用于响应
表现形式中进行选择 。“*”值不能被代理产生;它可能只能被源服务器产生。
14.45 Via
Via经常使用头域必须被网关(gateways)和代理(proxies)使用,用来指明在用户代理和服务器
之间关于请求的中间协议和接收者,和在源服务器和客户端之间关于响应的中间协议和接收者。
它和RFC822[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
received-protocol 指出沿着请求/响应链每一段的服务器或客户端所接收消息的协议版本。
protocol-version被追加于Via头域值后面,当消息被转发时。
只要协议是HTTP,那么protocol-name是无关紧要的。received-by头域一般是接收的转发服
务器的host(主机)和可选的port(端口)号,或接收的转发客户端的host(主机)和可选的
port(端口)号。然而,若是真实host(主机)被看做是信息敏感的,那么此主机可能会被别
名代替。若是port(端口号)没有被给定,那么它可能被假设为received-protocol 的缺省
port(端口)号。
Via头域里若是有多个域值,则每一个值分别表明一个已经转发消息的代理或网关。每个接收者
必须把它的信息追加到最后,因此最后的结果是按照转发应用程序的顺序来的。
comment(注释)可能被用于Via头域是为了指定接收者代理或网关的软件,这个比如User-
Agent和Server头域。然而,Via头域里全部的comment是可选的(译注:无关紧要的),并
且能够被接收者在转发消息以前移去。
例如,有一个请求消息来自于一个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)
被用做通向网络防火墙的入口的代理和网关在缺省状况下不该该转发host(主机)的名字和端
口到防火墙区域里。若是这些信息显示地指定要被传送,那么就应该被传送。若是此信息显示地
指定不能被传送,那么任何穿过防火墙而被接收的host(主机)应该用一个合适的别名替换。
为了隐藏组织结构的内部结构须要,一个代理(proxy)可能会在一个Via 头域中把相同
received-protocal值的项合成一个项。例如,
Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
将被折叠成
Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
应用程序不该该合并多个项,除非他们都在相同组织的控制下而且host(主机)已经被别名代
替了。应用程序不能合并不一样received-protocaol值的项。
14.46 Warning
Warning经常使用头域被用于携带额外关于消息状态或消息转换的信息,而这些信息是不能在消息
里反应出来的。这些信息一般被用于去警告因为缓存操做或消息主体转换带来的透明性
(semantic transparency)的缺失。
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
; the name or pseudonym of the server adding
; the Warning header, for use in debugging
warn-text = quoted-string
warn-date = <"> HTTP-date <">
一个响应可能携带多个Warning头域。
warn-text必须使用对于接收响应的用户来讲尽量理解的天然语言和字符集。找到用户自能理
解的天然语言和字符集,必须基于任何可能的知识,如缓存或用户的位置,请求里的Accept-
Language头域,响应里的Content-Language头域,等等。缺省语言是英语,缺省字符集是
ISO-8859-1。
若是字符集不是ISO-8859-1,那么它必须利用RFC2047里描述的来在warn-text里进行编码。
Warning头域能被应用于任何消息,然而,一些warn-codes是特定于缓存的,而且只能被应
用于响应消息。新的Warning头域应添加到任何已存Warning头域的后面。缓存不能删除任何它
接收到的消息里的Warning头域。然而,若是一缓存成功验证一缓存项,那么它应移除任何以
前依附于那个缓存项的Warning头域除了特定警告码(Warning codes)的Warning头域。然
后,它必须添加这个验证响应里的任何Warning头域。换句话说,Warning头域是依附于最近
相关响应的Warning头域。
当多个Warning头域被附加于一个响应里,那么用户代理应该通知用户尽量多的警告,而且
以它们呈如今响应里的顺序。若是用户代理不能通知用户全部的警告,那么用户代理应该按照
下面的规则:
- 前面的响应里的警告优于后面响应的警告
- 用户偏心的字符集的警告优于其它字符集的警告,但这除了warn-codes和warn-agents
一致的状况。
产生多个Warning头域的系统应该时刻记住利用用户代理行为来安排警告。
关于警告的缓存行为的要求在13.1.2里描述。
下面是当前定义的warn-codes,每个warn-code 都有一个建议性的以英语表示的warntext,
和它的意思的描述。
110 Response is stale
不管什么时候当返回响应是陈旧的时候,必须被包含。
111 Revalidation failed
若是一个缓存由于尝试去重验证响应失败而返回一个陈旧的响应(因为不能到达服务器),
必须被包含。
112 Disconnected operation
若是缓存在一段时间被有意地断开链接,应该被包含。
113 Heuristic expiration
若是缓存探索性地选择了一个保鲜寿命大于24小时而且响应的年龄大于24小时时,必须
被包含。
199 Miscellaneous warning
警告文本可能包含任意信息呈现给用户。除了呈现给用户警告,接收警告的系统不能采起任
何自动行为。
214 Transformation applied
若是一个中间缓存或代理采用任何对响应的内容编码(content-coding)(在Content-
Encoding头域里指定)或媒体类型(media-type)(在Content-Type头域里指定)的改变变,
或响应的实体主体(entity-body)的改变,那么此响应码必须被中间缓存或代理添加,除非此
警告码(warning code)已经在响应里出现。
299 Miscellaneous persistent warning
警告文本应该包含任意呈现给用户的任意信息。接收警告的系统不能采起任何自动行为。
若是一个实如今一个消息里发送多个版本是HTTP/1.0或更早的HTTP协议版本的Warning头
域,那么发送者必须包含一个和响应日期(date)相等的warn-date到每个Warning头域值
中。
若是一个实现收到一条warning-value里包含一个warn-date的消息,而且那个warn-date不
同于响应里的Date值,那么warning-value必须在保存,转发,或利用消息以前从消息里删除。
(这回防止本地缓存去缓存Warning头域的恶果。)若是全部warning-value由于这个缘由而被
删除,Warning头域必须也要被删除。
14.47 WWW-Authenticate
WWW-Authenticate响应头域必须包含在401(没有被受权)响应消息中。此域值至少应该包
含一个callenge,此callenge指明受权模式(schemes)和适用于请求URI的参数。
WWW-Authenticate =“WWW-Authenticate” “:” 1#challenge
HTTP访问受权过程在“HTTP Authentication: Basic and Digest Access Authentication”[43]里
描述。用户代理被建议特别当心去解析WWW-Authenticate 头域值,当此头域值包含多个
challenge,或若是多个WWW-Authenticate头域被提供且challenge的内容能包含逗号分隔的
受权参数的时候。
15.安全考虑 (Security Consideration)
这一部分是用来提醒程序开发人员,信息提供者,和用户关于HTTP/1.1安全方面的限制。讨论
并不包含对被披露问题的明确的解决办法,然而,它却对减小安全风险提供了一些建议。
15.1 我的信息 (Personal Information)
HTTP的客户端常常要对大量的我的信息保密(例如用户的名字,域,邮件地址,口令,密匙
等。),而且应当很是当心地防止这些信息无心识地经过HTTP协议泄露到其余的资源。咱们非
常强烈地建议应该给用户提供一个方便的界面来控制这种信息的传播,而且设计者和实现者在
这方面应该特别注意。历史告诉咱们在这方面的错误常常引发严重的安全和/或者隐私问题,并
致使对设计或实现者的公司产生很是不利的影响。
15.1.1服务器日志信息的滥用 (Abuse of Server Log Information)
服务器是用来保存用来指定用户读模型或感兴趣主题的请求的。这些信息一般显然是需保密的,
而且它的使用在某些国家被法律保护。利用HTTP协议提供数据的人们必须保证在这些数据被
许可的状况下分发。
15.1.2敏感信息的传输 (Transfer of Sensitive Inforamtion)
就像任何数据传输协议同样,HTTP不能调整传输数据的内容,也没有任何经验方法在任意给
定请求的背景里去判断特定信息的敏感性。所以,应用程序应该尽量为此信息提供者提供对
此信息的控制。在此背景里,有四个头域须要提出来,这四个头域是:Server,Via,Referer
和From。
揭露服务器特定软件版本信息可能会使服务器的机器更容易受到经过软件安全漏洞来进行攻击
的攻击。实现者应该使Server头域成为可设置的选项。
用做穿过网络防火墙入口的代理应该特别当心防火墙后能够辨别主机信息的头域信息被传输。
特别是,代理应移除在防火墙以后产生的任何Via头域。
Referer头域容许被学习的读模式和反向连接的跟踪。虽然它很是有用,但也会被滥用若是用户
细节没有从包含在Referer头域里信息里分离开来。即便当我的信息已经被移除了,Referer头
域也可能指定私有文档的URI(不能被公开)。
From头域里的信息可能会和用户的私有兴趣或他们站点的安全策略相冲突,所以From头域
不该被传输在用户没有能使此头域的内容失效、有效和更改的状况下。用户必须能在用户的喜好
或应用程序的缺省设置范围内设置此头域的内容。
咱们建议,尽管不须要,给用户提供一个方便的开关界面来使发送From和Referer头域有效
或失效。
User-Agent(14.4节)或Server(14.38节)头域有时候能被用来去判断一个特定的客户端或
服务器是否存在安全漏洞。不幸的是,一样的信息常常被用于其它有价值的目的,由于HTTP
当前没有更好的机制。
15.1.3 URI 中敏感信息的编码(Encoding Sensitive Information in
URI’s)
由于一个连接的源多是私有信息或者可能揭露其它私有信息源,因此强烈建议用户能选择是
否须要发送Referer头域。例如,浏览器客户端可能为了开放/匿名方式提供一个触发开关,此
开关可能使Referer头域和From头域信息的发送有效/无效。
若是参考页面在一个安全的协议上传输,客户端不该该包含一个Referer头域在一个非安全
HTTP请求里。
利用HTTP协议的服务做者不该该利用基于窗体GET提交敏感数据,由于这个能引发数据在
请求URI里被编码。许多已存在的服务,代理,和用户代理将在对第三方可见的地方记录请求
URI。服务器能利用基于窗体POST提交来取代基于窗体GET提交。
15.1.4 链接到Accept头域的隐私问题
Accept请求头域能揭露用户的信息给全部被访问的服务器。Accept-Language头域能揭露用户
的私有信息,由于能理解特定语言的人常常被认为就是某个特定种族里的成员。提供选项在每
次请求里去设置Accept-Language头域的用户代理被强烈鼓励让设置过程应包含一个让用户
知道本身隐私可能被会泄漏的消息。
一种限制隐私丢失的方法多是缺省为用户代理去遗漏Accept-Language头域的发送,而且
询问用户是否给开始给服务器发送Accept-Language头域,若是用户代理经过查看任何由服
务器产生的Vary响应头域时发现这个发送能提升服务的质量。
每个请求里的用户可配置的接受头域(accept header fields),特别是若是这些接受头域
(accept header fileds)包含质量值,那么应该被服务器用做相对信赖和长久的用户标识符
(user identifiers)。这样的用户标识符将会容许内容提供者进行点击跟踪以及容许合做内容提
供者匹配跨服务器点击跟踪或者造成单个用户窗体提交。注意对于许多并不在代理后面的用户,
运行用户代理的主机的网络地址也将做为长久用户的标识符。在代理被用做加强隐私的环境里,
用户代理应保守地提供接受(accept)头域配置选项给终端用户上。做为一种高度隐私的方式,
用户代理可能在接力的(relayed)的请求里的过滤接受头域。提供高度可配置性的用户代理应
警告用户会有隐私的泄漏。
15.2 基于文件和路径名称的攻击
HTTP的源服务器的实现应该限制HTTP请求返回的文档应是服务器管理员有意图的文档。如
果HTTP服务器要把HTTP URIs翻译成文件系统的调用,那么服务器必须当心去对待提供给
HTTP客户端的文件传输。例如,UNIX,微软Windows,和其余操做系统都利用“..”去指示当
前的父目录。对于这样一个系统,一HTTP服务器不容许任何这样的构造(construct)在请求
URI里,若是这个构造能在经过HTTP服务器访问以外能访问这个资源。一样的,用做对服务
器内部引用的文件(如访问控制文件,配置文件,脚本代码)必须受到保护而不让其被不合适
的获取,由于他们可能包含敏感的信息。经验告诉咱们一个在HTTP服务器实现里的一个小小
的错误会带来安全风险。
15.3 DNS欺骗
使用HTTP的客户端严重依赖于域名服务,所以这会致使基于IP和DNS名称的不关联的攻击。
客户端须要当心关注IP地址/DNS名称关联的持久合法性。
特别是,HTTP客户端为了确认IP地址/DNS名称关联性,应该依赖于客户端本身的的名称解
析器,而不该依赖缓存之前主机(host)名称查找(host name lookups)结果。许多平台在恰
当的时候可在本地缓存主机名称查找(host name lookups),而且他们应被配置为可这样作。
然而,只有当被名称服务器报告的TTL(Time To Live)信息指明被缓存的信息仍然有用时,
才能够缓存查找(lookups)。
若是HTTP客户端为了提升性能去缓存主机名称查找(host name lookups)的结果,那么他
必须观察被DNS报告的TTL信息。
若是HTTP客户端不能看到这条规则,那么,当之前访问的IP地址改变时,他们就会被欺骗。
由于网络地址的改变变得很日常,因此这种形式的攻击在不断增长。看到这个规则能减小潜在
的安全攻击的可能性。
此要求一样能改进客户端负载均衡(load-balancing)行为,由于重复的服务器能利用同一个
DNS名称,此要求能下降用户在访问利用策略(strategy)的站点中的体验失败。
15.4 Location头域和欺骗
若是单个的服务器支持互不信任的多个组织,那么它必须检查响应(在据称的组织的控制下产
生)里Location和Content-Location头域值,以确信这些头域不会使它们没有权限的资源无效。
15.5 Content-Disposition的问题
RFC 1806 [35],在HTTP中常用的Content-Disposition(见19.5.1节)头域就源于此文
档,有许多很是认真的安全考虑在此文档里说明。Content-Disposition并非HTTP标准版本
中的一部分,但自从它被普遍应用以来,咱们正在证实它对使用者的价值和风险。详细资料见
RFC 2183 [49](对RFC 1806的升级)。
15.6 受权证书和空闲客户端
现有的HTTP客户端和用户代理一般会不明确地保留受权信息。HTTP/1.1并无为服务器提供
一个方法让服务器去指导客户端丢弃这些缓存的证书(credentials)。这是一个重大缺陷,此
缺陷须要扩展HTTP协议来解决。在某些情形下,缓存证书会干涉应用程序的安全模型,这些
情形包含但不局限于:
 这样的客户端。此客户端空闲已到达必定时间,服务器可能但愿再次使客户端让用户
出示证书。
 这样的应用程序。此应用程序包括了一个会话中断指令(例如在一页上有“退出”或
者“提交”的按钮),根据此指令,服务器端“知道”不须要更多理为客户端保留证
书。
这是做为当前独立研究的。有不少解决这个问题的社区,而且咱们鼓励在屏幕保护程序、空闲超
时、和其余能减轻安全问题的方法里利用密码保护。特别是,能缓存证书的用户代理被鼓励去提
供一个容易的访问控制机制,让在用户控制下丢弃缓存的证书。
15.7 代理和缓存 (Proxies and Caching)
本质上说,HTTP代理是中间人(men-in-the-middle),而且存在中间人攻击(man-in-themiddle
attacks)危险。系统(代理运行于其上)的缺陷能致使严重的安全和隐私问题。代理拥
有对相关安全信息、用户和组织的我的信息、和属于用户和内容提供者的专有信息的访问权限。
一个有缺陷的代理,或一个没有考虑安全性和隐私性的代理可能会被委托用来攻击。
代理操做者应该保护代理运行其上的系统,正如他们保护任何包含或传输敏感信息的系统同样。
特别是,代理上收集的日志信息常常包含较高的我的敏感信息,和/或关于组织的信息。日志信
息应该被当心的保护,而且要合适地开发利用。(见15.1.1)节。
代理的设计者应当考虑到设计和编码断定所涉及到的隐私和安全问题,以及他们提供给代理操
做人员配置选项(尤为是缺省配置)所牵涉到的隐私和安全问题。
代理的用户须要知道他们自比运行代理的操做员更不值得信赖;HTTP协议自身不能解决这个
问题。
在合适的时候,对密码学的正确应用,可能会保护普遍的安全和隐私攻击。密码学的讨论不在
本协议文档的范围内。
15.7.1 关于代理的服务攻击的拒绝
代理是存在的。代理很难被保护。关于此研究正在进行。
16 感谢(Acknowledgment)
这份规范大量使用了扩展BNF和David为RFC 822 [9]定义的经常使用结构。一样的,它继续使用
了不少Nathaniel Borenestein和Ned Freed为MIME [7]提供的定义。咱们但愿在此规范里他们
的结论有助于减小过去在HTTP和互联网邮件消息格式关系上的混淆。
HTTP协议在这几年已经有了至关的发展。它受益于大量积极的开发人员的社区--许多人已经通
过www-talk邮件列表参与进来--而且一般就是那个社区对HTTP和万维网的成功做了重大贡献。
Marc Andreessen, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-
Francois Groff , Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob McCool, Lou
Montulli, Dave Raggett, Tony Sanders, 和 Marc VanHeyningen由于他们在定义协议早期方面
的贡献应该获得特别的赞誉。
这篇文档从全部那些参加HTTP-WG的人员的注释中得到了很大的益处。除了已经提到的那些
人之外,下列人士对这个规范作出了贡献:
Gary Adams Ross Patterson
Harald Tveit Alvestrand Albert Lunde
Keith Ball John C. Mallery
Brian Behlendorf Jean-Philippe Martin-Flatin
Paul Burchard Mitra
Maurizio Codogno David Morris
Mike Cowlishaw Gavin Nicol
Roman Czyborra Bill Perry
Michael A. Dolan Jeffrey Perry
David J. Fiander Scott Powers
Alan Freier Owen Rees
Marc Hedlund Luigi Rizzo
Greg Herlihy David Robinson
Koen Holtman Marc Salomon
Alex Hopmann Rich Salz
Bob Jernigan Allan M. Schiffman
Shel Kaphan Jim Seidman
Rohit Khare Chuck Shotton
John Klensin Eric W. Sink
Martijn Koster Simon E. Spero
Alexei Kosut Richard N. Taylor
David M. Kristol Robert S. Thau
Daniel LaLiberte Bill (BearHeart) Weinman
Ben Laurie Francois Yergeau
Paul J. Leach Mary Ellen Zurko
Daniel DuBois Josh Cohen
缓存设计的许多内容和介绍应归于如下人士的建议和注释:Shel Kaphan, Paul Leach, Koen
Holtman, David Morris, 和 Larry Masinter。
大部分规范的范围是基于Ari Luotonen和John Franks早期作的工做,以及从Steve Zilles另
外加入的内容。
感谢Palo Alto的"cave men"。大家知道大家是谁。
Jim Gettys(这篇文档如今的编者)特别但愿感谢Roy Fielding,这篇文档之前的编者,连同
John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen Holtman, John Franks, Josh
Cohen, Alex Hopmann, Scott Lawrence, 和Larry Masinter一块儿感谢他们的帮助。还要特别感
谢Jeff Mogul和Scott Lawrence对“MUST/MAY/ SHOULD”使用的检查。
Apache 组,Anselm Baird-Smith,Jigsaw 的做者,和Henrik Frystyk 在早期实现了RFC
2068,咱们但愿感谢他们发现了许多这篇文档正尝试纠正的问题。
19 附录
19.1 互联网媒体类型message/http和application/http
这篇文档除了定义HTTP/1.1 协议外,同时还被做为互联网媒体类型“message/http”和
“application/http”的规范。此类型用于封装一个HTTP请求消息或响应消息,这假设此类型遵
循MIME 对 全部“消息”类型关于行长度和编码的限制。application/http类型能够用来封装一
个或者更多HTTP请求或响应信息(非混合的)的管线(pipeline)。下列是在IANA[17]注册的。
媒体类型名称: message
媒体子类型名称: http
必须参数: 无
可选参数: 版本,信息类型
版本:封装信息的HTTP版本号(例如,"1.1")。若是不存在,版本能够从消息的第
一行肯定。
信息类型:信息类型--"请求"或者"响应"。若是不存在,类型能够从报文的第一行肯定。
编码考虑:只有"7bit","8bit",或者"二进制"是容许的。
安全考虑:无
媒体类型名称: application
媒体子类型名称: http
必须参数: 无
可选参数: 版本,信息类型
版本:封装信息的HTTP版本号(例如,"1.1")。若是不存在,版本能够从报文的第
一行肯定。
信息类型:信息类型--"request"或者"response"。若是不存在,类型能够从报文的第一
行肯定。
编码考虑:用这种类型封装的HTTP信息是"二进制"的格式;当经过E-mail传递的时
候一种合适的内容传输编码是必须的。
安全考虑:无
19.2 互联网媒体类型multipart/byteranges
当一个HTTP 206(部份内容)响应信息包含多个范围的内容(请求响应的内容有多个非重叠
的范围),这些是做为一个多部分消息主体来被传送的。这种用途的媒体类型被称
做"multipart/byteranges"。
multipart/byteranges 媒体类型包括两个或者更多的部分,每个都有本身Content-type 和
Content-Range头域。必需的分界参数(boundary parameter)指定分界字符串,此分界字符
串用来隔离每一部分。
媒体类型名称: multipart
媒体子类型名称: byteranges
必须参数: boundary
可选参数: 无
编码考虑:只有"7bit","8bit",或者"二进制"是容许的。
安全考虑:无
例如:
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-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--
注意:
1)在实体(entity)中,在第一个分界字符串以前能够有多余的CRLFs。
2)虽然RFC 2046 [40]容许分界字符串加引号,可是一些现有的实现会不正确的处理分界字
符串
3)许多浏览器和服务器是按照字节范围标准的早期草案关于使用multipart/x-byteranges媒体
类型来进行编码的的,这个草案不老是彻底和HTTP/1.1中描述的版本兼容。
19.3 放松的应用程序 (Tolerent Applications)
虽然这篇文档列出了HTTP/1.1消息所必须的元素,可是并非全部的应用程序都能正确地实
现。所以咱们建议运行程序能够容忍误差只要这些误差能被无歧义的理解。
客户端应该放松地解析Status-Line(状态行);服务器也应该放松地解析Request-Line(请
求行)。特别的,他们应该能够接受头域之间任何数量的SP或HT字符,即便协议规定只有一
个SP。
消息头域的行终结符是CRLF。然而,当解析这样的头域时,咱们建议应用程序能识别单一LF
做为行终结符并能忽略CR。
实体主体(entity-body)的字符集应该被标记为应用于实体主体字符编码的最小公分母,而且
指望不对实体进行标记要优于对实体标记为US-ASCII或ISO-8859-1。见3.7.1和3.4.1。
对关于日期分析和编码的要求的额外规则以及其它对日期编码的潜在问题包含:
 HTTP/1.1客户端和缓存应该假定一个彷佛是50多年之后的RFC-850日期其实是过去
的(这有助于解决"2000年"问题)。
 一个HTTP/1.1的实现能够内部地表示一个比正确日期值更早的已解析后的Expires日期,
可是必定不要(MUST NOT)内部地表示一个比正确日期值更迟的已解析过的Expires日
期。
 全部过时日期相关的计算必须用GMT时间。本地时区必定不能(MUST NOT)影响年龄
或过时时间的计算。
 若是一个HTTP头域不正确的携带了一个非GMT时间区的日期值,那么必须利用最保守
的可能转换把此日期值转换成GMT时间值。
19.4 HTTP实体和RFC 2045实体之间的区别
HTTP/1.1 使用了许多Internet Mail ( RFC 822 [9] ) 和Multipurpose Internet Mail
Extensions(MIME [7])里定义的结构,去容许实体以多种表现形式和扩展机制去传输。然而,
RFC2045讨论邮件,而且HTTP有许多不一样于RFC2045里描述的特征。这些不一样被当心地挑
选出来优化二进制链接的性能,为了容许使用新的媒体类型有更大的灵活性,为了使时间比较
变得容易,和为了认可一些早期HTTP服务器和客户端的实效。
本附录描述了HTTP协议不一样于RFC 2045的特殊区域。在严格的MIME环境中的代理和网关
应该意识到这些不一样而且在必要的时候要提供合适地转换。从MIME环境到HTTP的代理和网
关也须要意识到这些不一样由于一些转换多是须要的。
19.4.1 MIME版本(MIME-Version)
HTTP不是一个遵照MIME的协议。然而HTTP/1.1消息能够包含一个单独的MIME-Version常
用头域用来指出什么样的MIME协议版本被用于去构造消息。利用MIME-Version头域指明彻底
遵循MIME协议的消息(在RFC2045[7])。代理/网关要保证彻底遵照MIME协议当把HTTP
消息输出到严格MIME环境的时候。
MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
在HTTP/1.1用的缺省值是MIME1.0版本。然而,HTTP/1.1消息的解析和语义是由本文档而不
是MIME规范定义的。
19.4.2 转换到规范化形式 (Conversion to Canoical Form)
RFC 2045 [7]要求一互联网邮件实体在被传输以前要被转换成一个规范化的形式,这在
RFC2049[48]里第四章里描述的。本文档的3.7.1节描述了当用HTTP协议传输时容许使用的
“text”子媒体类型的形式。RFC2046要求类型为“text”的内容要用CRLF表示为换行符,以及
在换行符外禁止使用CR或LF。
RFC 2046须要像在“text”类型的内容里同样,用CRLF表示行间隔符并禁止在行间隔符序列
之外使用CR或者LF。HTTP容许CRLF,单个CR,和单个LF来表示一个换行符在一个文本
内容消息中。
在可能的地方,从HTTP到MIME严格环境的代理或网关应该把RFC2049里描述的text媒体
类型里全部换行符转换成RFC2049 里CRLF 的规范形式。然而,注意这可能在Content-
Encoding出现的时候,以及HTTP容许利用一些没有利用13和10表明CR和LF的字符集时
候都会变得复杂。
实现者应该注意转换将会破坏任何应用于源内容(original content)的密码校验和,除非源内
容已是规范化形式。所以,对任何在HTTP中使用校验和的内容被建议要表示为规范化形式。
19.4.3 日期格式的转换 (Conversion of Date Formate)
为了简化日期比较的过程,HTTP/1.1使用了一个限制的日期格式(3.3.1节)。其它协议的代
理和网关应该保证任何消息里出现的Date头域应该遵循HTTP/1.1规定的格式,若是有必要需
要重写此日期。
19.4.4 Content-Encoding头域介绍 (Introduction of Content-Encoding)
RFC 2045不包含任何等价于HTTP/1.1里Content-Encoding头域的概念。由于这个头域做为
媒体类型(media type)的修饰,从HTTP协议到MIME遵照协议的代理和网关在转发消息之
前必须既能改变Content-Type头域的值,也能解码实体主体(entity-body).。(一些为互联网
邮件类型的Content-Type 的实验性应用有使用一个媒体类型参数“; conversions=<contentcoding>”
去执行等价于Content-Encoding的功能。然而,此参数并非RFC2045的部分)
19.4.5 没有Content-Transfer-Encoding头域
HTTP不使用RFC 2045里的Content-Transfer-Encoding(CTE)头域。从使用MIME协议到
HTTP 的代理和网关在把响应消息发送给HTTP 客户端以前必须删除任何非等价(nonidentity
, 译注: identity 编码, 表示没有进行任何编码) CTE ( "quotedprintable"
或"base64")编码。
从HTTP到MIME协议遵循的代理和网关要确保消息在那个协议安全传输上是用正确的格式和
正确的编码,“安全传输”是经过使用的协议的限制而被定义的。这样一个代理或网关应该用
合适的Content-Transfer-Encoding头域来标记数据若是这样作将提升安全传输的可能性。
19.4.6 Transfer-Encoding头域的介绍
HTTP/1.1介绍了Transfer-Encoding头域(14.41节)。代理/网关在转发经由MIME协议的消
息以前必须移除任何传输编码。
一个解码"chunked"传输代码(3.6节)的程序能够用代码表示以下:
length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
19.4.7 MHTML和行长度限制
和MHTML实现共享代码的HTTP实现须要了解MIME行长度限制。由于HTTP没有这个限制,
HTTP并不折叠长行。用HTTP传输的MHTML消息遵照全部MHTML的规定,包括行长度的限
制和折叠,规范化等,由于HTTP传输全部消息主体(见3.7.2)而且不解析消息的内容和消
息中包含任何MIME头域。
19.5 其它特征
RFC 1945和RFC 2068里一些协议元素被一些已经存在的HTTP实现使用,可是这些协议元
素对于大多数HTTP/1.1应用程序既不兼容也不正确。实现者被建议去了解这些特征,可是不能
依赖于它们的出现或不依赖于与其它HTTP/1.1应用程序的互操做性。这些特征中的一些特征描
述了实验性的特征,以及还有一些特征描述了没有在基本HTTP/1.1规范里被描述的实验性部
署特征。
一些其它头域,如Content-Dispositon和Title头域,他们来自于SMTP和MIME协议,他们
一样常常被实现(见2076[37]).
19.5.1 Content-Disposition
Content-Disposition响应头域被建议做为一个这样的用途,那就是若是用户请求要使内容被保
存为一个文件,那么此头域被源服务器使用去建议的一个缺省的文件名。此用途来自于
RFC1806[35]关于对Content-Disposition的定义。
content-disposition = "Content-Disposition" ":"
disposition-type *( ";" disposition-parm )
disposition-type = "attachment" | disp-extension-token
disposition-parm = filename-parm | disp-extension-parm
filename-parm = "filename" "=" quoted-string
disp-extension-token = token
disp-extension-parm = token "=" ( token | quoted-string )
一个例子是:
Content-Disposition: attachment; filename="fname.ext"
接收用户的代理不该该(SHOULD NOT)关注任何在filename-parm参数中出现的文件路径
信息,这个参数被认为在此次仅仅是应用于HTTP实现。文件名应该(SHOULD)只被看成一
个终端组件。
若是此头域用于一个Content-Type为application/octet-stream响应里,那么含义就是用户代
理不该该展示响应,可是它应该直接进入一个‘保存响应为…’对话框。
见15.5节关于Content-Disposition的的安全问题。
19.6 和之前版本的兼容
要求和之前的版本的兼容超出了协议规范的范围。然而HTTP/1.1有意设计成很容易支持之前的
版本。必须值得注意的是,在写这份规范的时候,咱们但愿商业的HTTP/1.1服务器去:
--接受HTTP/0.9,1.0和1.1请求的请求行(Request-Line)格式;
--理解HTTP/0.9,1.0或1.1格式中的任何有效请求;
--恰当地用客户端使用的主要版原本响应。
而且咱们但愿HTTP/1.1的客户端:
--接受HTTP/1.0和1.1响应的状态行(Status-Line)格式;
--懂得HTTP/0.9,1.0或1.1的格式的任何有效的响应。
对大多数HTTP/1.0的实现,每个链接要在请求以前被客户端创建,而且在发送响应以后要
被服务器关闭。一些实现了在RFC 2068 [33]的19.7.1节描述的持久链接的Keep-Alive版本。
19.6.1 对HTTP/1.0的改变
这一部分总结HTTP/1.0和HTTP/1.1之间主要的区别。
19.6.1.1 对多主机web服务器和保留IP地址简化的改变
客户端和服务器都支持Host请求头域,而且若是Host请求头域在HTTP/1.1请求里没有出现
必须报告一错误,而且服务器能接受一个绝对URIs(5.1.2节),这些要求是此规范里最重要
的改变。
旧的HTTP/1.0客户端会认为IP地址和服务器是一对一关系;没有其它机制去区分IP地址和
目标服务器。上面的改变将容许互联网,一旦旧客户端再也不广泛使用时,能够去支持一个IP地
址对应多个web站点的状况,这大大简化了大型的web运行服务器,在那上面上分配多个IP
地址给一个主机(host)会产生严重问题。互联网照样能恢复这样一个IP地址,此IP地址做为
特殊目的被分配给被用于根级(root-level)HTTP URLs的域名。给定web的增加速度和服务
器的部署数量,那么全部HTTP实现(包括对已存HTTP/1.0应用程序)应该正确地知足下面
这些需求:
--客户端和服务器都必须支持Host请求头域。
--发送HTTP/1.1请求的客户端必须发送Host头域。
--若是HTTP/1.1请求不包括Host请求头域,服务器必须报告错误400(Bad Request)。
--服务器必须接受绝对URIs(absolute URIs)。
19.6.2 和HTTP/1.0持久链接的兼容
一些客户端和服务器可能但愿和一些之前持久链接实现的HTTP/1.0客户端和服务器保持兼容。
HTTP/1.0持久链接须要显式地协商,由于持久链接不是HTTP/1.0的缺省行为。关于持久链接
的HTTP/1.0实验性实现存在缺陷,而且HTTP/1.1里的新的功能被设计成去矫正这些问题。这
个缺陷是:一些已经存在的1.0客户端可能会发送Keep-Alive头域给不理解持久链接的代理,
而后代理会把此Keep-Alive转发给下一个内向(inbound)服务器。结果是HTTP/1.0客户端必
须禁止利用Keep-Alive,当和代理会话的时候。
然而,和代理进行会话最重要是利用持久链接,因此那个禁止很显然不能被接受。所以,咱们
须要一些其它的机制去指明须要一个持久链接,而且它必须能安全地被使用甚至是当和忽略持
久链接的旧代理会话。持久链接缺省是为HTTP/1.1消息的;为了声明非持久链接(见14.10
节),咱们介绍一个新的关键字(Connection:close)。
持久链接的源HTTP/1.0的形式(Connection: Keep-Alive 和 Keep-Alive 头域)在RFC2068
里说明
19.6.3 对RFC 2068的改变
这篇规范已经被仔细的审查来纠正关键字的用法和消除它们的歧义;RFC 2068在遵照RFC
2119 [34] 制定的协定方面有不少问题。
澄清哪一个错误代码将会使入流服务器失灵(例如DNS失灵)。(10.5.5节)
CREATE有一个特色当一个资源第一次被建立的时候必须须要一个Etag。(10.2.2节)
Content-Base头域今后规范里删除了:它没法普遍的实现,而且在没有健壮的扩展机制的情
况下,没有简单的,安全的方式去介绍它。而且,它以一种类似的而不是相同的方式在
MHTML[45]里被使用。
略…..
20 索引 (Index)
21 所有版权声明
略…..html

相关文章
相关标签/搜索