网络之HTTP协议

网络之HTTP协议

定义

连接(connection)
为通信而在两个程序间建立的传输层虚拟电路。
消息(message)
HTTP通信中的基本单元。它由一个结构化的八比特字节序列组成,与第4章定义的句法相匹配,并通过连接得到传送。
请求(request)
一种HTTP请求消,。
响应(response)
一种HTTP响应消息。
资源(resource)
一种网络数据对象或服务,可以用第3.2节定义的URI指定。资源可以以多种表现方式(例如多种语言,数据格式,大小和分辨率)或者根据其它方面而而不同的表现形式。
实体(entity)
实体是请求或响应的有效承载信息。一个实体包含元信息和内容,元信息以实体头域(entity-header 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)需要代理认证和代理识别,而不修改请求或响应。非透明代理(non-transparent 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)”。

总体操作

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节)。

版本

HTTP使用一个“.”数字模式来指明协议的版本号。为了进一步的理解HTTP通信,协议的版本号指示了发送端指明消息的格式和能力,而不仅仅是通过双方通信而获得的通信特性。当消息元素的增加不会影响通信行为或扩展了域值时,协议版本是不需要修改的。当协议会因为添加一些特征而做了修改时,数字就会递增。这些修改不会影响通常的消息解析算法,但它会给消息添加额外的语意(semantic)并且会暗示发送者具有额外的能力。协议的消息格式发生变化时,数字就会增加。
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)在版本里有或没有而进行改变。

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)名称。

字符集

一些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头域里提供了字符集,并且用户代理也支持这种字符集的显示,不管用户代理是否愿意,它必须要利用这种字符集。

HTTP消息

消息类型(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。

消息头 (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 combinationsof
token, separators, and quoted-string>

filed-content不包括任何前导或后续的LWS(线性空白):线性空白出现在域值(filed-value)的第一个非空白字符之前或最后一个非空白字符之后。前导或后续LWS可能会在不会改变域值语意情况下被删除。任何出现在filed-content之间的LWS可能在解析域值之前或把这个消息往下流传递时会被一个SP代替。. 不同域名的头域被接收的顺序是不重要的。然而,首先发送常用头域,然后紧接着是请求头域或者是响应头域,然后是以实体头域结束,这样做是一个好的的方法。 如果一个头域的域值被定义成一个以逗号隔开的列表,那么使用同一个域名(filed-name)的多个消息头域可能会出现在一些消息中。不改变消息的语义,可以把相同名的多个头域结合成一个“域名:域值”对的形式,这可以通过把每一个后续的域值加到第一个里,每一个域值用逗号隔开的算法实现。同名头域的接收顺序对合并的域值的解释是有重要意义的,所以代理(proxy)当把消息转发时不能改变域值的顺序。

消息主体 (Message Body)

HTTP消息的消息主体用来承载请求和响应的实体主体(entity-body)的。这些消息主体(message-body)仅仅当被传输译码头域(Transfer-Encoding)指明的传输编码(transfer-coding)应用于实体主体(entity-body)时才和实体主体相区别,其它情况消息主体和实体主体相同。传输译码头域在14.41节阐述。
message-body=entity-body|
传输译码头域被用来指明应用程序的传输编码,它是为了保证消息的安全和合适的传输。传输译码(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)。所有其他的响应必须包括消息主体,即使它长度可能为零。

消息的长度(Message Length)

当消息主体出现在消息中时,一条消息的传输长度(transfer-length)是消息主体(message-body)的长度;也就是说在实体主体被应用了传输编码(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)和传输长度(transfer-length)两者不相等(也就是说,出现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)当接收了一个无效的长度时必须能通知用户。

请求(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

请求行 (Request-Line)

请求行(Request-Line)是以一个方法标记开始,后面跟随Request-URI和协议版本(HTTP-Version),最后以CRLF结束。元素是以SP字符分隔。除了最后的CRLF,CR或LF是不被允许的。
Request-Line =Method SP Request-URL SP HTTP-Version CRLF

方法 (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章指定的相同。

请求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。

请求资源的识别 (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节
| Referer 14.36节
|TE 14.39节
| User-Agent 14.43节
请求头域的名字是能被扩展,但只能随协议版本改变而被扩展。然而新的或实践性的头域可以给定请求头域语义,如果所有通信方都把它看作请求头域。不能识别的头域会被看作实体头域(entity-header)。

响应 (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节

状态行 (Status-Line)

响应消息的第一行是状态行(stauts-Line),由协议版本以及数字状态码和相关的文本短语组成,各部分间用空格符隔开,除了最后的CRLF序列,中间不允许有CR或LF。
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

状态码与原因短语 (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)应当把响应的实体展现给用户,因为实体有可能包括人类可读的信息,这些信息也许能解释非正常状态的原因。

响应头域 (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节
响应头域的名字能依赖于协议版本的变化而扩展。然而,新的或者实践性的头域可能会给予响应头域的语义如果通信所有成员都能识别他们并把他们看作响应头域。不被识别的头域被看作实体头域。

原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值