分类: 系统运维
2008-09-24 09:16:45
在提出持久连接之前,每获取一个URL都有创建一个单独的TCP连接,不断的加重HTTP服务器的负担并导致网络的拥塞。使用内联的图片或者相关数据常常使得客户端在很短时间内发送众多的请求。问题分析和原型实现的结果的分析已经有了[26][30]。HTTP/1.1的实现的执行体验和测算都有很好的结果[39]。实现方式也都被研究过,例如T/TCP[27]。
持久HTTP连接具有一下优势:
l 通过打卡和关闭更少的TCP连接,节省了路由和主机的CPU耗时,以及TCP协议控制阻塞使用的主机内存。
l HTTP请求和响应可以在一个连接的基础上管道化。管道技术允许客户端发送多个请求而不用等待响应,使得TCP连接更加高效地使用从而更少的浪费时间。
l 通过减少TCP打开导致的包的消息来减少网络拥塞,通过给TCP充分的时间来确定网络的拥塞状态。
l HTTP可以进化的更加优美,因为错误可以被报告而不用直接关闭TCP连接。使用高HTTP版本的客户端可能尝试一些新的功能,但是如果与旧版本服务端通信时在有错误报告后用要重试旧的语义。
HTTP实现应该实现持久连接。
HTTP/1.1和早期HTTP版本最大的不同是持久连接是HTTP连接的默认行为。也就是说,除非有其他的标识,客户端应该假设服务器会持有一个持久连接,即使服务端返回错误的响应。
持久化连接提供了一个机制可以让客户端和服务端给出TCP连接关闭的信号。信号用Connection报头域给出(14.10章)。一旦关闭信号发出,客户端就不能再通过那个连接发送任何请求。
一个HTTP/1.1服务端可以假定HTTP/1.1客户端会持有一个持久连接,除非发送的请求里有一个Connection报头域里包括连接符号“close”。如果服务器选择在发送响应后立刻关闭连接,它应该发送一个有关闭连接符号的Connection报头域。
HTTP/1.1客户端可以认为一个连接是始终打开的,但决定其保持打开是基于服务端的响应里是否包含一个有关闭连接符的Connection报头。如果客户端不想在请求之后继续持有连接,那么他应该发送一个有关闭连接符号的Connection报头。
如果客户端或者服务端发送了有关闭符号的Connection报头,那个请求就是连接的最后一次使用。
为了保持持久连接,所有经由连接的消息都必须有一个自定义的消息长度(例如关闭连接所没有定义的那个),4.4章对消息长度有描述。
支持持久连接的客户端可以“管道”其请求(例如发送多个请求而不用等待每个响应)。服务必须按照接收请求的顺序发送响应。
采取持久化连接和在创建连接后立即管道化的客户端应该在其第一次管道化尝试失败时重试其连接。如果客户端进行这样的重试,它在确定连接是持久的之前不能进行管道化。客户端也必须准备好重发那些请求,如果服务端在没有返回相应响应就关闭了连接的话。
客户端不应该使用non-idempotent方法或者non-idempotent方法序列来管道化请求。否则的话,一个传输连接的过早的中止可能会导致不确定的结果。那些想发送non-idempotent请求的客户端应该等到它接收到前一个请求的响应状态码之后再发送请求。
代理正确地实现14.10章指出的Connection报头域的属性是非常重要的。
代理服务器必须分别想其连接的客户端和源服务端(或者是另一个代理服务器)通知持久化连接。没一个持久化连接只能应用到一个传输链接上。
代理服务器不能同HTTP/1.0客户端创建一个HTTP/1.1连接。(不过可以看一下RFC 2068
[33]关于一些HTTP/1.0客户端实现的Keep-Alive报头的信息和问题讨论)。
服务端通常会有一些超时值,一旦超出之后将不再保持不活动的连接。代理服务器可以设一个大一些的值,因为客户端可能有很多连接经由同一个服务器。持久连接没有对服务端或者客户端的超时长度做出要求。
当一个客户端或者服务端认为超时时它应该给传输连接一个完美的中断。客户端和服务端都应该密切监视对方的传输中断,并做出适当的响应。如果客户端或者服务没有察觉对方的关闭可能会导致不必要的网络资源浪费。
客户端、服务端或者代理可能会在任何时候关闭传输连接。例如一个客户端可能已经发送新请求的同时服务端也决定关闭这个无用的连接。从服务的角度看是在关闭失效的连接,但客户端的角度则是正在发送一个请求。
这意味着客户端、服务端和代理应该有能力从异步连接关闭事件中恢复过来。客户端应该重新打开传输连接并且重发失败了请求序列而不用用户交互,只要请求序列是等价的(idempotent)(参看9.1.2章)不等价的方法或者序列不能自动重发,尽管用户代理可能会提交给用户一个重发请求的选择。有程序语义识别的用户代理可以代理用户做出确认。自动重发在第二次请求失败后不应该继续重复。
服务端应该始至少响应每个连接中的一个请求,如果可能的话。服务端不应该在传输响应的中途关闭连接,除非是网络或者客户端错误。
使用持久连接的客户端应该限制其与给定服务端维持的并行性连接数量。一个单用户保持的域服务器或者代理的连接不应该超过2个。代理应该使用最多2*N个与服务或者代理的连接,这里N是并发的活跃用户的数目。这些指导意见是用来改善HTTP响应时间并避免拥塞。
HTTP/1.1服务端应该保存一个持久连接并使用TCP的流控制机制来解决临时性的重载,而不是终止那些客户可能会重试的连接。后者会加剧网络的拥塞。
HTTP/1.1 (或者以后的)客户端在发送消息体时应该监控网络以便在其传输请求是发现错误状态。如果客户端发现了错误的状态,它应该立刻中止消息体的传输。如果消息体是用“”编码的方式传输,一个零长度块和空trailer可以用来提前标识消息的结束。如果消息体已经加上了Content-Length报头,客户端应该关闭连接。
100(继续)状态(参看10.1.1章)的目的是允许一个正在发送有请求主体的请求消息的客户端在发送消息主体之前确定源服务是否接受该请求(取决于请求报头)。在一些情况下,如果服务端不用查看主体就拒绝消息而客户端继续发送消息主体是不合适也是很非常浪费时间的。
对HTTP/1.1客户端的要求:
l 如果客户端在发送请求主体前会等待一个100(Continue)响应,它必须发送一个有“100-continue”预期的请求报头。
l 客户端不能发送一个有“100-continue”请求报头域的请求,如果它不打算发送请求主体。
由于有老版本的实现,协议允许不明确的状态,这样客户端可以发送“Expect: 100-continue”而不用收到417(期望失败)或者100(继续)状态。因此,当客户端发送一个报头域给源服务端(或许经由代理)但未收到100(Continue)状态时,客户端不应该无限等待下去。
对HTTP/1.1源服务端的要求:
l 当接收到一个包含带有“100-continue”期望报头域的请求后,源服务端必须要么返回100(Continue)状态继续读取输入流,要么给出一个最终响应代码。服务端在发出100(Continue)响应之前不能等待请求主体。如果给出的是最终状态码,服务端可以关闭传输连接,也可以继续读取并丢弃请求的剩余部分。服务端不能执行请求的方法,如果它返回的是一个最终状态码。
l 一个源服务端不应该在请求信息里没有“100-contiune”期望报头域的情况下返回100(Continue)响应,如果请求来自HTTP/1.0服务器那么它也不能返回100状态。这个规则有一个例外就是:为了兼容草案2068,服务端可以发送一个100状态响应给一个,没有包含有“100-continue”期望请求报头域的HTTP/1.1的PUT或者POST请求。这个例外的目的是为了最小化客户端处理未声明的等待100状态造成的延迟,这只能应用于HTTP/1.1请求,不针对其他HTTP版本。
l 一个源服务应该不再发送一个100响应,如果它已经接收到相应请求的部分或者全部的请求实体。
l 一个发送过100响应的源服务端必须在请求实体接收并处理后发送一个最终状态代码,除非它提前中止了传输连接。
l 如果源服务接收到一个不包括含有“100-continue”期望值的期望请求报头域,请求包含一个请求实体,并且服务在从传输连接中读取全部请求体之前发送了最终状态码,那么服务端不应该关闭传输连接知道它已经读取了全部请求,或者知道客户端关闭了连接。否则的话,客户端可能没有可靠地接收响应信息。虽然如此,这个要求不是妨碍服务端防止拒绝服务式攻击或者有严重缺陷的客户端实现。
对HTTP/1.1代理的要求:
l 如果代理接收到一个包含有“100-continue”期望值的期望请求报头域的请求,并且代理知道下一环服务端是HTTP/1.1或者更高版本,或者不知道下一环服务器HTTTP版本,它必须传递请求,包括期望报头域。
l 如果代理知道下一环服务端是HTTP/1.0或者更低的版本,它必须不转寄请求,并且要返回一个417(期望失败)状态。
l 代理应该缓存最近引用的下一环服务器的HTTP版本号。
l 代理必须不能转寄100响应,如果请求消息来自于HTTP/1.0(或者更早的版本)客户端并且不包含有“100-continue”期望值的期望请求报头域。这个要求不考虑推进1xx响应的一般规则。
如果一个HTTP/1.1客户端发送了一个包含请求实体的请求,但是请求不包含有“100-continue”期望值的期望请求报头域,并且如果客户端不是直接连接到一个HTTP/1.1源服务器上,并且如果客户端发现在从服务端接收到任何状态之前连接已经关闭,客户端应该重发这个请求。如果客户端不想重发这个请求,它也可以使用接下来的“binary exponential backoff”机制来确定获取一个可好的响应:
1. 创建一个到服务端的新连接
2. 传输请求报头域
3. 用估计服务的反馈时间(例如基于它创建连接所用的时间),或者一个5秒的常值来初始化一个变量R
4. 计算 T = R*(2**N),N是上一次重试的次数。
5. 等待到从服务返回一个错误响应,或者T秒(两者最先的那个)。
6. 如果没有错误返回,在T秒后传输请求实体。
7. 如果客户端发现连接提前关闭了,返回到步骤1知道请求被接收、接收到错误的响应或者用户不耐烦并中止重试过程。
如果在任一步接收到一个错误的状态,客户端
l 不应该继续并且
l 应该关闭连接,如果它没有完成请求信息的发送。
下面定义了HTTP/1.1通用的方法集合。尽管这个集合是可以扩展的,增加的方法在单独扩展的客户端和服务端里不能共享上述的语义。
Host请求报头域必须存在于所有的HTTP/1.1请求。
实现者应该知道软件代表用户在其通过因特网进行交互,并且应该小心的让用户知道他们将要采取的动作,这些动作可能会对其自身或者其他参与者有不可预期的影响。
特别指出的是,按照协定GET和HEAD方法不应该有出获取资源以外的能力。这些方法应该被认为是安全的。这就允许用户代理用特殊的方式来表现其他的方法,例如GET、PUT和DELETE,这样用户就可以知道请求的是一个可能不安全的动作。
自然地,不能保证服务端执行GET请求时不会产生副作用;事实上,一定动态资源认为它一个特性。这最重要的区别是用户没有请求副作用,因为不应该让他们承担责任。
由于 N>0个相同请求的副作用同一个单独的请求是一样的,方法也可以具有等冥特性。方法GET,HEAD,PUT和DELETE共享这个属性。通用,方法OPTIONS和TRACE应该不会有副作用,也是天生等冥的。
虽然如此,一些请求的序列可能是非冥等的,即使所有在序列中执行的方法是冥等的。(一个序列是冥等的是指整个序列的一次单独执行结果不会因为重新执行该序列的全部或者部分而改变。)例如,如果序列的结果依赖于一个可能稍后会在同一个序列中做出修改的值,则该序列是非冥等的。
根据定义,没有副作用的序列是冥等的(前提是没有并发的操作在同一个资源上执行)
OPTIONS 表示一个请求来获得关于请求URI指定的请求/响应链上的可用通讯选项信息。这个方法允许客户端自行决定资源相关或者服务端能力的选项和(或)要求,而不用指示一个资源动作或者发起一个资源获取。
这个方法的响应是不可缓存的。
如果OPTIONS请求含有实体主体,那么必须通过一个Content-type域来指定媒体类型。虽然本规范里并没有定义怎样使用这个主体,将来的HTTP版本可能或使用OPTIONS主体对服务端做更详细的查询。如果服务器不支持这样的扩展可以丢弃请求主体。
如果请求URI是一个星号(*), OPTIONS请求只是对服务器自身的一般应用而不是针对特定资源。例如,它可以被用来测试代理对HTTP/1.1的兼容性。
如果请求URI不是星号,那么OPTIONS请求只是申请当与资源通讯时有效的选项。
一个200响应应该包含一些报头域来值标示服务端实现的功能选项或者资源的可用性(若Allow),也肯包含一些本规范里为定义的扩展。响应主体,如果有的话,也应该包含通讯选项的相关信息。这种主体的格式规范没有去定义,但是可能在将来的HTTP扩展里定义。内容协商可能会用来选择适当的响应格式。如果响应不包哈响应主体,那么它应该给出一个域值为“0”的Content-Length域。
Max-Forwards请求报头域可以用来选择请求链中的特定代理。当一个代理收到可以继续传播的绝对URI的OPTIONS请求时,代理必须检查Max-Forwards报头域。如果Max-Forwards报头域的值是零(“0”),代理不能转发消息;取而代之,代理应该响应其自身的通讯选项。如果Max-Forwards域值是一个大于0的整数,代理必须在转发请求时递减这个域值。如果没有Max-Forwards域出现在请求里,转发的请求里也绝不能包含Max-Forwards域值。
GET方法表示取回请求URI指定的任意信息(实体的表单)。如果请求URI引用了一个数据生产进程,它生成的数据会作为响应的实体返回而不是进程的资源文本,除非文本出现在进程的输出中。
如果请求信息包含If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match或者 If-Range报头域,那么GET方法的语义将变成“conditional GET”。一个条件GET方法请求只有在条件报头域描述的环境下实体才会被传输。条件GET方法允许刷新缓存实体而不用提出多个请求或者传输客户端已经拥有的数据,籍此减少不必要的网络使用。
如果请求信息里包含Range报头域,GET方法的语义会变为“partial GET”。一个部分GET请求只传输实体的一部分,参考14.35章的描述。部分GET方法是通过允许部分获取实体而不用传输客户端已拥有的数据来减少网络的使用。
GET请求的响应可以缓存,条件是当且仅当其符合13章描述的HTTP缓存要求。
参看15.1.14章使用表单时的安全考虑。
除了服务端不能在响应中返回消息体,HEAD方法等同于GET。存在于响应HEAD请求的HTTP报头的元信息也应该同样出现在GET请求的响应里。这个方法可以被用来获取请求所指的实体的元信息而不必传输实体主体本身。这个方法最常用于测试超文本连接的有效性、可访问性以及最近的修改。
如果响应信息可以用来更新一个以前缓存的来自资源的实体,那么HEAD请求的响应是可以缓存的。如果新的域值指出缓存的实体不同于当前的实体(可能是Content-Length, Content-MD5, ETag
或者 Last-Modified的改变),缓存应该将缓存的实体丢弃。
使用POST方法的请求中,源服务端接收附加在请求里的实体,作为请求行里请求URI所指定的隶属资源。POST被设计成具有以下功能的统一方法:
l 声明存在资源;
l 投递消息给一个公告板、新闻组、邮件列表或者类似的主题。
l 提供数据块给一个数据处理进程,如提交表单的结果。
l 通过增加操作来扩充数据库。
POST所提供的实际功能取决于服务端并且通常受制于请求URI。投送的实体从属于URI如同文件从属于拥有它的路径一样,就像一个新的文章从属于它投递的新闻组,或者记录从属于数据库。
POST方法执行的动作可能不会生成可以通过URL可以指定的资源。这种情况下,200(OK)或204(无内容)谁是一个恰当的响应状态,依赖于响应是否包含一个描述结果的实体。
如果服务端已经创建了资源,响应应该是201(Created)并且包含一个描述了请求状态和新资源相关的实体,以及一个Location报头(参看14.30章)。
这个方法的响应是不能缓存的,除非响应包含适当的Cache-Control或者Expires报头域。虽然如此,303 (See Other)响应可以用来引导客户代理来检索一个可缓存的资源。
参看15.1.3章关于安全的建议。
PUT方法要求附加的实体保存它所提供的请求URI下。如果请求URI提到的是一个已经存在的资源,附加的实体应该被当作现在服务器上已有版本的修改。如果请求URI没有指向一个存在的资源,那么这个URI可以被作为请求的用户代理所定义的一个新资源,而服务器可以使用这个URI创建资源。如果资源被创建,源服务端必须通过201(创建)响应通知客户代理。如果是一个存在的资源被修改,应该发送200(OK)或者204(无内容)响应码来指出请求的成功完成。如果请求URI资源不能创建或者修改,应该返回恰当的错误响应来反映错误的种类。实体接收者不能忽略任何它不识别或者没有实现的Content-*(例如 Content-Range)报头,相反在这种情况它必须返回一个501(未实现)响应。
如果请求通过缓存或者请求指定了一个或多个当前缓存的实体,这些实体应该被丢弃。此方法的响应是不能缓存的。
POST和PUT请求根本的不同源自请求URI的含义不同。POST请求中的URI标识了处理附加实体的资源。那个资源可能是数据接受进程,一个其他协议的网关或者一个允许接收注解的单独的实体。相反,PUT请求里的URI指定了请求附带的实体——用户代理知道URI想要的并且服务端不能试图将请求应用到其它资源上。如果请求希望请求应用到不同的URI上,那么它必须发送一个301(永久转移)响应;关于是否要重定向请求可以由用户代理自己做出决定。
多个不同的URI可能会指定同一个资源。例如,一个主体可能会有一个标识“当前版本”的URI,这跟标识每个特定版本的URI是有区分的。这种情况下,一个普通URI上的PUT请求可能导致源服务定义一些其它的URI。
HTTP/1.1没有定义PUT方法如何影响一个源服务端的状态。
PUT请求必须遵守8.2章给出的消息传输要求。
除非领带指定一个特殊的实体报头,PUT请求里的实体报头应该应用到PUT所创建或修改的资源。
DELETE方法是请求源服务端删除请求URI指定的资源。这个方法可能会被源服务端上人为因素(或者其它手段)重写。客户端不能保证操作会被执行,即使源服务给出的状态码标识动作已经被成功执行。虽然如此,服务端不应该标识成功,除非在响应给出时它已经计划要删除资源或者将其转移到不可访问的位置。
如果响应包含描述状态的实体,成功的响应应该是200(OK),如果动作没有执行则返回202(接受的),或者如果动作已经执行但是响应里不包含实体则返回204(无内容)。
如果请求通过一个缓存或者请求URI标识了一个或多个当前的缓存实体,这些实体应该被丢弃。此方法的响应是不可缓存的。
TRACE方法使用来调用一个远程的应用程序层的请求信息的循环返回。请求的最终接收者应该将接收到的信息作为200响应的实体主体反射回客户端。最终的接收可能是接收到一个源服务端或者是第一个在请求中接收到0值Max-Forwards的代理或网关。TRACE请求不能包含实体。
TRACE允许客户端查看请求链的另一端接收到了什么以及是使用那些数据测试或者诊断信息。Via报头域的值有特殊的作用,它扮演了请求链的跟踪者的俄角色。使用Max-Forwards报头域允许客户端限制请求链的长度,这对测试一个无限循环投送信息的代理链是很有用的。
如果请求是有效的,响应应该将全部的请求信息包含来实体主体中,并且有一个“message/http”的
Content-Type。此方法的响应不能被缓存。
规范预留了一个CONNECT方法名让代理动态的切换为一个隧道(如 SSL隧道)。
每个状态码都在下面进行了描述,包括其对应的方法和响应所需要的元信息。
这个类别的状态码标识了一个临时的响应,只有状态行和自定义报头组成,由一个空行中止。此类别状态码没有必须的报头。因为HTTP/1.0没有定义1xx状态码,除非在实验情况下服务端不能发送1xx响应给HTTP/1.0客户端。
一个客户端必须准备在接受到正式的响应之前接受一个或多个1xx响应,即使客户端不期望一个100(继续)状态信息。未预期的1xx状态响应可以被用户代理忽略。
代理必须转递1xx响应,除非在客户端和客户端的连接被关闭,或者代理自身请求所产生的1xx响应。(例如:如果代理转递请求时添加一个“Expect:100-continue”域,那么它可以不必转递相应的100(继续)响应)。
客户端应该继续这个请求。这个临时的响应用来通知客户端请求的最初部分已经接收到并且没有被服务拒绝。客户端应该通过继续发送剩余的请求,或者如果请求已经完成,则忽略此响应。服务端必须在请求完成后发送一个最终的响应。参看8.2.3对使用和处理此状态码的详细讨论。
服务端理解并准备应答客户端的请求,通过Upgrade消息报头域来改变连接使用的程序协议。服务端会在发送完终止101响应的空行后立即切换为响应Upgrade报头域指定的协议。
协议应该在这样做有利的情况下进行切换。例如,切换为一个新的版本的HTTP协议比旧的协议有好处,而切换为一个实时的,同步的协议可能在处理使用此类功能的资源时更有利。
此类状态码标识客户端的请求被成功接收、理解并接受。
请求已经成功。响应返回的信息取决于请求所用的方法。例如:
GET 响应返回一个对应于请求资源的实体。
HEAD 响应返回一对应于请求资源的实体报头域,没有消息主体。
POST 一个实体描述或保存动作的结果。
TRACE 一个包含服务接收的请求信息的实体。
请求被完成并导致新资源被创建。新创建的资源可以被返回响应实体中的URI引用,其中最准确的URI由Location报头域给出。响应应该包含一个含有资源特征列表的实体,用户或者用户代理可以从里面选择最合适的位置。实体格式由Content-Type报头域给出的媒体类型给出。源服务必须在返回201状态码之前返回响应。如果动作不能被立刻执行,服务端应该用202(接受)响应代替。
一个201响应可能含有一个ETag响应报头域标识请求变量创建的实体标记的当前值,参看14.19章。
请求已经被接受来处理,但处理还没有被完成。请求有可能会或者不会被遵行,因为它可能在处理过程中被拒绝。从一个异步操作中重发这样一个状态码是不容易的。
202响应是有意无委托的。它的目的是允许某些处理的请求(可能是一个批量处理会运行一天)不用要求用户代理到服务端的连接一直持续到处理完成。该响应的实体应该包含一个请求当前状态的标识,以及一个状态监控器的指示器或者一些用户可以判断请求何时被完成的估计。
返回实体报头域中的元信息不是服务端用到的最终设置,但它是一个本地或者第三方拷贝推测出来的。这个设置可能是源版本的子集或者超集。例如,包含生成源服务知道的元信息超集的冠以资源的本地注释信息。这个代码的使用不是必需的,只是当响应会是200的时候才使用。
服务已经完成请求但不需要返回一个实体主体,而可能需要返回更新元信息。响应的实体报头列表应该包含新的或者更新的元信息,这些信息应该与请求的变量相关。
如果客户端是一个用户代理,它不应该改变它的会导致请求发送的文档视图。这个响应是有意为允许动作的输入发生时不会导致用户代理的活动文档视图哥改变,虽然一些新的或者更新的元信息应该被应用到当期用户代理的活动视图的文档上。
204响应不能包含消息体,因此总是由报头域后的空行终止。
服务端已经完成请求并且用户代理应该重置文档视图造成请求的发送。这个请求是有意允许动作的输入通过用户输入发生,跟着一个给出输入的清空列表,这样用户可以很容易的开始另一个输入动作。响应不能包含实体。
服务端完成资源的部分GET请求。请求必须包含一个Range报头域(14.35章)标识想要的范围,并且可以包含一个If-Range报头域(14.27章)来给出请求的条件。
响应必须包含以下报头域:
l 一个Content-Range报头域(14.16章)标识想拥有包含的范围,或者一个多部分/字节范围的Content-Type包含每一部分的Content-Range域。如果一个Content-Length报头域出现在响应中,它的值必须与消息体中传输的OCTET的实际数目相匹配。
l Date
l ETag 和(或)Content-Location,如果报头已经由200响应发送给同一个请求的话。
l Expires, Cache-Control, 和/或Vary,如果域值可能不同于以前发送的响应里的同一变量。
如果206响应是一个使用强缓存校验的If-Range请求的结果,响应不应该包含其他的实体报头域。如果响应是一个使用弱校验的If-Range请求的结果,响应必须不能包含其它的实体报头域;这避免了缓存实体主体和更新的报头的矛盾。否则的话,响应必须包含所有的实体报头,那些已经同200响应返回给同一个请求的报头。
一个缓存必须不能将一个206响应和以前缓存的内容相结合,如果Etag或者Last-Modified报头没有完全匹配,参看13.5.4章。
不支持Range和Content-Range报头的缓存必须不能缓存206响应。
这个类别的状态码标识用户代理要做出进一步的动作来完成请求。要求的动作可以在不用与用户交互的情况下由用户代理发出,前提是当且仅当下一个请求使用的方法是GET或HEAD。客户端应该监测无限重定向循环,因为这样的循环会造成每个重定向的网络拥塞。
注意:规范的早期版本推荐了一个5次重定向的最大次数。开发者应该知道可能有实现了固定限制的客户端。
请求资源对应于一组表示的任一个成员,每一个都有自己特定的位置,并且提供了代理驱动的协商信息,因此用户(或者用户代理)可以选择一个首选表示并重定向其请求到该位置。
除非是一个HEAD请求,响应应该包含有资源字符列表和位置的实体,由此客户或者客户代理可以选择最一个合适的。实体格式由报头域Content-Type给出的媒体类型指定。依托于格式和盈沪代理的能力,选择最合适的选项可以被自动执行。尽管如此,文档没有定义自动选择的标准。
如果服务有一个首选的表示选择,它应该在Location域里包含该表示的明确的URI;用户代理应该可以使用Location域值作为首选重定向。响应是可以缓存的,除非有其它的标识。
请求资源被分配给一个新的永久性的URI,将来对此资源的引用都应该使用返回URI中的某一个。具有关联编辑能力的客户端应该在那些可能的地方自动重连到请求URI的引用,变更为由服务返回的一个或多个引用。响应是可缓存的,除非有其它的标识。
新的永久性的URI应该由响应中的Location域给出。除非请求方法是HEAD,响应的实体应该包含一个有执行新URI的超链接的简短的超文本注释。
如果在一个非GET或者HEAD请求的响应里接收到301状态码,用户代理必须不能自动重定向请求除非它可以被用户确认,因为这可能改变请求的初衷。
注意:当在接收到一个301状态码后自动重定向一个POST请求时,一下已有的HTTP/1.0用户代理可能错误的将它改变为一个GET请求。
请求资源临时性的放在一个不同的URI下。因为重定向有时会被更该,客户端应该在以后的请求中继续使用这个请求URI。响应只能在有Cache-Control或者Expires报头域标识时才能缓存。
临时性的URI应该由响应的Location域给出。除非请求方法是HEAD,响应的实体应该包含一个有新URL超链接的简短的超文本描述。
如果一个非GET或HEAD请求的响应里接收到302状态码,用户代理不能自动重定向请求,除非用户确认,因为这可能会改变请求的初衷。
注意:RFC1945和RFC2068规定不允许客户端改变重定向请求的方法。不过,绝大多数的用户代理实现将302作为303响应对待,在Location域值上执行一个GET方法而忽略原来的请求方法。状态码303和307已经添加给那些确定客户端所期望反作用种类的服务端。
请求的响应可以在不同的URI下找到并且应该应该使用一个GET方法来重新获取资源。这个方法出现的初衷是为了允许POST脚本来重定向用户代理选择资源。新URI不是源请求资源的替换引用。303响应不能被缓存,但第二次(重定向)请求的响应是可以缓存的。
这个不同的URI应该由响应的Location域给出。除非请求方法是HEAD,响应实体应该包含一个有指向新URI的超链接的简单超文本注释。
注意:很多HTTP/1.1前的用户代理不识别303状态。如果与这种客户端进行交互,应该使用302状态码代替,因为大多数用户代理对302的反应类似于这里描述的303。
如果客户端执行了一个有条件的GET请求并且访问被通过,但是文档并没有被修改,服务应该给出一个此状态码的响应。304响应不能包含一个消息体,因此在读取报头域后面的空行通常终止读入。
响应必须包含一下报头域:
l Date,除非它的冗长是14.18.1章要求的。
如果一个无锁的源服务要求这些规则,并且代理和客户端添加自己的Date到一个没有该域的响应里,缓存应该做出合适的处理。
l Etag和/或Content-Location,如果报头已经由200响应发送给同一个请求。
Expires, Cache-Control, 和/或 Vary,如果域值可能不同于以前发送响应中的同一个变量。
如果条件GET使用了一个强缓存校验(13.3.3章),响应不应该包含其他的实体报头。否则(条件GET使用弱校验),响应不能包含其他实体报头;这预防了缓存实体主体和更新报头的矛盾。
如果一个304响应标识了一个当前没有被缓存的实体,缓存必须忽略响应并无条件的重发请求。
如果缓存使用一个接收到的304响应更新缓存实体,缓存必须更新实体来映射响应给出的新的域值。
请求资源必须通过Location域给出的代理访问。Location域给出了代理的URI。接收者被期望通过代理重发单独的请求。305响应只能由源服务端给出。
注意:RFC 2068没有明确305是要重发单一的请求,并且只能由源服务产生。不注意这些限制会产生重大的安全隐患
306状态码在规范的以前版本中使用,以后不再使用,代码作为保留值。
请求资源临时放在不同的URI下。由于重定向可能会在必要时修改,客户端应该在以后的请求中继续使用请求URI。响应只有在一个Cache-Control或者Expires报头域标识的时候才可以缓存。
临时的URI应该由响应的Location域给出。除非请求方法是HEAD,响应的实体应该含有一个指向新URI的超链接的简短超文本描述,因为很多HTTP/1.1以前的用户代理不识别307状态。所以,描述应该包含一个用户重发基于新URI的原始请求是所必须的信息。
如果307状态码响应对应的请求方法不是GET或者HEAD,用户代理不能自动重发请求除非经由用户同意,因为这可能会改变请求的初衷。
4xx类别的状态码是当客户端象是出错的时使用的。除了对HEAD请求的响应,服务端应该包含一个对错误情形进行解释的实体,不论它是一个临时的还是永久性的状况。这些状态码适用于任意请求方法。用户代理应该将包含的实体展示给用户。
如果客户端正在发送数据,使用TCP实现的服务端应该在关闭输入连接前,仔细确保客户端确认收到响应包含的包。如果客户端在关闭后继续向服务端发送数据,服务端的TCP栈将向客户端发送一个重置包,它将在客户端未确认的输入缓存被读取并在HTTP应用解析他们之前将其丢弃。
服务端由于请求语法错误不能理解请求。客户在做出修改前不应该重发请求。
请求要求用户验证。响应必须包含一个WWW-Authenticate报头(14.47章)满足请求资源的提问能力。客户端可以重发有一个适配的Authorization的报头域的请求(14.8章)。如果请求里已经包含了认证证书,那么应该返回401响应来标识对于那些证书的认证被拒绝。如果401响应里包含了同上一个响应相同的提问,并且用户代理已经至少尝试了一次认证,那么它应该让用户知道响应所给出的实体,因为实体中可能包含相关的诊断信息。HTTP访问认证在"HTTP Authentication: Basic and Digest Access Authentication"【43】 中有所解释。
此代码留作将来使用
客户端理解请求,但是拒绝完成它。认证不会有帮助,请求不应该被重发。如果请求犯法不是HEAD并且服务希望公布请求未被处理的原因,它应该在实体里描述被拒绝的原因。如果服务不希望客户端知道这个信息,它可以使用代码404(未发现)代替。
服务没有找可匹配请求URI的资源。不标识状况是临时的还是永久的。如果服务端通过一些内部配置机制知道一个旧资源永久不可用并且没有推进的地址,它应该使用410(Gone)状态码。
这个状态码是在服务端不希望展现为什么服务被拒绝或者没有其他响应可用的时候使用。
请求URI指定的资源不接收请求队列指定的方法。响应必须包含一个Allow报头,给出一个请求资源的可用方法列表。
请求指定的实体依照请求发送的接受报头只能生成内容特征不被接收的响应实体。
除非是一个HEAD请求,响应应该给出一个含有可用实体特征列表的实体,以及用户或者用户代理可以选择的一个更恰当的位置。实体格式Content-Type报头域给定的媒体类型来指定。依靠格式和用户代理的能力,最合适的选择可能会自动完成。不过,此规范并没有定义自动选择的标准。
注意:HTTP/1.1服务端允许返回请求允许报头中不允许的响应。在有些情况中,这比返回406响应会更可取。我们鼓励用户代理检查响应中的报头来决定它是否可接收。
如果响应不能被接收,用户代理用该临时性停止接收更多的数据并询问客户决定下一步操作。
这个代码类似于401(未授权),不过它标识客户端首先要向代理认证它自身。代理必须返回一个Proxy-Authenticate报头域,它包含了用于代理对请求资源的提问能力。代理可以重发一个有适配Proxy-Authenticate报头域的请求(14.34章)。HTTP访问认证在“HTTP Authentication:
Basic and Digest Access Authentication” 有解释。
客户端没有在服务端所能等待的时间里产生请求。客户端可以稍后重发无须更改请求。
由于资源的当前状态有冲突导致请求未能完成。这个代码只有在预期客户端有能力解决冲突并重新提交请求的情况下使用。响应体应该包含足够的信息来让客户认识冲突的资源。理想情况下,响应实体应该包哈足够的信息让客户或者客户代理定位问题;不过,那样可能不现实也不是必需的。
冲突最可能发生在对PUT请求的响应里。例如,如果使用了版本控制并且PUT的实体包含了对某个资源的变更,而这又跟早一点(第三方)的请求所产生的相冲突,服务端可以使用409响应来标识出它不能完成请求。这种情况下,响应实体最好包含一个两个版本的差异的列表,其格式由响应的Content-Type来定义。
请求资源不再可用并且没有推进的地址。这种情况被认为是永久性的。有链接编辑功能的客户端应该在征得用户同意后删除该请求URI的引用。如果服务端不知道,或者没有能力决定,无聊状况是否是永久性的,应该使用404(未发现)代替。响应是可缓存的除非有其他标识。
410响应主要用来通过通知接收者资源有意地无法获取并且服务拥有者要去删除资源的远程链接辅助web维护工作。这个事件通常在限制时间,增值服务以及个人所属资源不再在服务端站点工作时发生。没有必要标记所有的永久性不可用资源为“gone”或者将标记保持一段时间——那是留给服务端拥有者去决定的。
服务端拒绝一个没有定义Content-Length的请求。客户端可以重发请求,如果它增加了一个Content-Length报头域来存放请求信息的消息主体的长度。
测试服务器时一个或多个请求报头域给出的预处理评估为错误的。这个响应代码欲寻客户端在当前资源元信息(报头域值)放置前提,并由此防止请求方法被用到非客户端想要的资源上。
服务决绝处理一个请求,原因是请求实体超过服务端想要或者能够处理的大小。服务端可能会关闭与客户端的连接来方式客户端继续请求。如果是临时的情况,服务端应该包含一个Retry-Afte报头域来标识它是临时的,客户端可以等一会重试。
服务拒绝应答请求,因为请求URI的长度长处服务能解释的范围。这种少见的情况往往发生在客户端错误将一个POST请求转换为有很长查询信息的GET请求、客户端掉进一个重定向URI黑洞(如重定向URI的前缀指向了自己的后缀)或者服务受到尝试探测出现在那些使用固定长度缓存来读取或者处理请求URI的服务端的安全漏洞的客户端的攻击。
服务端拒绝请求,原因是请求的实体使用了请求方法请求的资源无法支持的格式。
当一个请求包含一个Range请求报头域,并且该域没有范围指定值与当选中资源的当前范围重叠,而请求又没有包含If-Range请求报头域时,服务端应该返回这个状态代码的响应。(byte-ranges以为折所有字节范围指定值的第一个字节位置要大于选中资源的当前长度)。
当这个状态码是返回给byte-range请求时,响应应该包含一个Content-Range实体报头域来指出所选资源的当前长度(参看14.16章)。这个响应不能使用multipart/byteranges内容类型。
Expect请求报头域给出的期望不能被服务满足,或者服务有确凿的证据表明请求不能被下一个服务满足。
响应状态码以5开头表示服务器知道自己出错或者没有能力执行请求。除响应HEAD请求外,服务应该包含一个实体,实体给出错误形式的解释,以及是一个临时还是永久的状况。用户代理应该展示给用户所包含的实体。这些响应码适用于任何请求方法。
服务器遇到意外情况,致使无法完成请求。
服务器不支持要完成请求的所需要的功能。这是当服务器不能识别请求方法和没有能力支持方法所需要的资源时恰当的响应。
当服务但当一个网关或者代理的角色,尝试实现请求时从访问的上游服务器接收到一个无效的响应。
由于暂时过载或者服务端维护导致当前服务不能处理请求。这意味着只是一个暂时的状况,稍后会得到环节。如果知道,延迟的长度可以用一个Retry-Afte报头标识。如果没有给出Retry-After,客户端应该自行处理此响应。
注意:503状态码的存在并不是强制服务端在过载时使用它。某些服务可能希望简单的拒绝连接。
作为一个网关或代理的服务端,没有从URI(如HTTP, FTP, LDAP)指定的上游服务器或者它要完成请求所需要访问的辅助服务器(例如 DNS)那儿接收到及时的响应。
注意:实现者应该注意:一些已有的代理在DNS查找超时时会返回400或者500。
服务器不支持或者拒绝支持请求里所有的HTTP协议版本。服务器指出不能或者不想使用与客户端相同的主版本来完成请求,如3.1章所描述,而不是返回错误信息。响应应该包含一个实体来描述为什么版本不被支持以及服务器所支持的其他协议。