HTTP协议<5>

Posted on 2005-09-23 11:51 英雄 阅读(1362) 评论(0)  编辑  收藏 所属分类: HTTP1.1协议中文翻译

5 请求

一个从clientserverrequest,在第一行,包含应用于资源的方法,资源标志,和使用的协议版本。

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

51请求行

以一个方法标记开始,跟着URI,和版本协议,以CRLF结束。SP分隔。除了在最后的CRLF不能有CRLF

Request-Line = Method SP Request-URI SP HTTP-Version CRLF

5.1.1方法

方法标记表示将会用在请求资源上的方法,是大小写敏感的。

Method = "OPTIONS" ; Section 9.2

| "GET" ; Section 9.3

| "HEAD" ; Section 9.4

| "POST" ; Section 9.5

| "PUT" ; Section 9.6

| "DELETE" ; Section 9.7

| "TRACE" ; Section 9.8

| "CONNECT" ; Section 9.9

| extension-method

extension-method = token

一个资源可以允许的方法列表可以在ALLOW头区给出。Response的返回代码总是告诉client一个方法可否应用到一个资源,因为总是在变。一个server应该返回405如果方法可以识别但不能用于请求资源,返回501如果方法不可识别或没有被origin server实现。方法gethead必须被所有的通用目的的server实现。所有其他方法是可选的;但是,如果上面的方法被实现,他们必须具备sec9定义的语义。

512URI

是一个统一资源标记(32)标记了request请求的资源。

Request-URI = "*" | absoluteURI | abs_path | authority

4个选项取决于request的性质。星号意思是request并不指定某一特定资源,而是server本身,只在方法并不一定针对资源时。一个例子:

OPTIONS * HTTP/1.1

如果请求是发给一个代理,absoluteURI形式是必须的。代理被请求来传递request或从一个有效缓存中服务,返回response。注意代理可以传递这个request给另外一个代理或直接给被absoluteURI指定的server。为了避免request循环,一个代理必须能够识别所有它的server名,包括别名,局部变量,和IP地址。里:

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

为了允许传递所有的未来的HTTP版本中的request,所有的HTTP/11server必须接收requestabsoluteURI,即使HTTP/11client只产生他们用来代理。

Authority形式只被CONNECT方法使用。(sec9.9)

最通用的URI形式是用来标记在一个origin servergateway上的资源。在这种情况下,URI的绝对路径(abs_path)必须作为URI被传递,而且URI的网络路径(authority)也必须被作为一个Host头区被传递。例如,一个希望直接从origin server得到上面指定资源的request会创建一个到“www.w3.org80端口的TCP连接并且发送这一行:

GET /pub/WWW/TheProject.html HTTP/1.1

Host: www.w3.org

跟着的是request的其他剩余部分。注意绝对路径不能是空的;如果确实没有,必须作为“/”给出。

URISEC321给出的格式传送。如果URI使用”%HEX HEX”编码[42]的形式编码,origin server必须解码URI一合适的解释requestServer应该对无效的URI给出合适的状态码返回。

一个transparent proxy当把request传递给内部server时绝对不能重写接收到的URI的“abs_path”部分,除非把null abs_path用“/”替换。

注意:“no rewrite”阻止了proxy改变request的原本意义,当origin server使用非保留URI字符对应保留目的时。实现者应该意识到一些HTTP/11proxy可能重写uri

52 Request标记的资源

被一个request请求的资源由urihost头区精确确定。

当决定一个HTTP/1/1request请求的资源时,一个origin server如果不允许使用host来区别资源,那么可以忽略host头区。(sec19.6.1

而一个确实使用host(又叫虚拟主机)区分资源的origin server使用下面原则处理HTTP/11request请求的资源:

 

  1.如果URIabsoluteURI,那么主机名是其中一部分,任何其他主机名头区被忽略。

  2.如果URI不是,并且包含HOST头区,那么host被头区决定。

  3400反馈12无效的。

HTTP/10是没有HOST头区的,可以使用直观推测方法来决定请求的精确资源。

53请求头区

头区允许client传递额外的关于requestclient的自身信息给server。这些区就算request的描述符,就象程序语言的参数一样。

request-header = Accept ; Section 14.1

| Accept-Charset ; Section 14.2

| Accept-Encoding ; Section 14.3

| Accept-Language ; Section 14.4

| Authorization ; Section 14.8

| Expect ; Section 14.20

| From ; Section 14.22

| Host ; Section 14.23

| If-Match ; Section 14.24

| If-Modified-Since ; Section 14.25

| If-None-Match ; Section 14.26

| If-Range ; Section 14.27

| If-Unmodified-Since ; Section 14.28

| Max-Forwards ; Section 14.31

| Proxy-Authorization ; Section 14.34

| Range ; Section 14.35

| Referer ; Section 14.36

| TE ; Section 14.39

| User-Agent ; Section 14.43

s头区的名字可以跟随一个改变的版本号而被扩展。但是,新的或实验的头区可以被给通用头区的语义如果通讯双方都认同。认不出的头区被认为是实体头区。

6 Response

当接收和解析一个request message后,一个server用一个HTTPresponse messge返回。

Response = Status-Line ; Section 6.1

*(( general-header ; Section 4.5

| response-header ; Section 6.2

| entity-header ) CRLF) ; Section 7.1

CRLF

[ message-body ] ; Section 7.2

61状态行

一个response message的第一行是状态行,由协议版本,跟状态码,跟对应文本段,每一个用SP分隔。没有CRLF被允许除了最后的CRLF

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

611状态码和原因段

状态码是一个3数字位结果编码,去理解和满足请求。Sec10完全定义。原因段是给一个简短的文本描述给status-code。状态码是自动使用而原因段是人工使用。Client并不需要去检查和表示原因段。

第一位定义了response的分类。后2位没有分类的意思。第一位有5个值。

· 1xx: request收到,继续处理

· 2xx: action被成功接收,理解,接受

· 3xx:还有其他action要做

· 4xx: request有问题

· 5xx: server有问题不能解决有效request的请求。

下面是定义的值和推荐原因段,当然可以自己定义。

Status-Code =

"100" ; Section 10.1.1: Continue

| "101" ; Section 10.1.2: Switching Protocols

| "200" ; Section 10.2.1: OK

| "201" ; Section 10.2.2: Created

| "202" ; Section 10.2.3: Accepted

| "203" ; Section 10.2.4: Non-Authoritative Information

| "204" ; Section 10.2.5: No Content

| "205" ; Section 10.2.6: Reset Content

| "206" ; Section 10.2.7: Partial Content

| "300" ; Section 10.3.1: Multiple Choices

| "301" ; Section 10.3.2: Moved Permanently

| "302" ; Section 10.3.3: Found

| "303" ; Section 10.3.4: See Other

| "304" ; Section 10.3.5: Not Modified

| "305" ; Section 10.3.6: Use Proxy

| "307" ; Section 10.3.8: Temporary Redirect

| "400" ; Section 10.4.1: Bad Request

| "401" ; Section 10.4.2: Unauthorized

| "402" ; Section 10.4.3: Payment Required

| "403" ; Section 10.4.4: Forbidden

| "404" ; Section 10.4.5: Not Found

| "405" ; Section 10.4.6: Method Not Allowed

| "406" ; Section 10.4.7: Not Acceptable

| "407" ; Section 10.4.8: Proxy Authentication Required

| "408" ; Section 10.4.9: Request Time-out

| "409" ; Section 10.4.10: Conflict

| "410" ; Section 10.4.11: Gone

| "411" ; Section 10.4.12: Length Required

| "412" ; Section 10.4.13: Precondition Failed

| "413" ; Section 10.4.14: Request Entity Too Large

| "414" ; Section 10.4.15: Request-URI Too Large

| "415" ; Section 10.4.16: Unsupported Media Type

| "416" ; Section 10.4.17: Requested range not satisfiable

| "417" ; Section 10.4.18: Expectation Failed

| "500" ; Section 10.5.1: Internal Server Error

| "501" ; Section 10.5.2: Not Implemented

| "502" ; Section 10.5.3: Bad Gateway

| "503" ; Section 10.5.4: Service Unavailable

| "504" ; Section 10.5.5: Gateway Time-out

| "505" ; Section 10.5.6: HTTP Version not supported

| extension-code

extension-code = 3DIGIT

Reason-Phrase = *<TEXT, excluding CR, LF>

HTTP状态码是可扩展的。HTTP应用并没有被要求去理解他们但很明显是需要的。但是,应用必须理解代码的分类,也就是第一位,并且对任何不认识的response等同于对应类别的x00,但是不缓存它。例如,如果一个431client接收到但不识别,它可以认为它的request本身并没有错,并且把response作为400处理。在这种情况下,user agent应该给user展现response返回的整个entity,因为entity可能包含人可以识别的信息来解释不寻常的状态。

62 Response 头区

用来让server放在status-line中不能放的关于response的额外信息。这些头区给出了server的信息和更深入的关于REQUEST-URI指定的资源进入。

response-header = Accept-Ranges ; Section 14.5

| Age ; Section 14.6

| ETag ; Section 14.19

| Location ; Section 14.30

| Proxy-Authenticate ; Section 14.33

| Retry-After ; Section 14.37

| Server ; Section 14.38

| Vary ; Section 14.44

| WWW-Authenticate ; Section 14.47

s头区的名字可以跟随一个改变的版本号而被扩展。但是,新的或实验的头区可以被给通用头区的语义如果通讯双方都认同。认不出的头区被认为是实体头区。

7  Entity

requestresponse可以传递一个实体如果request方法和response状态码未加限制的话。一个entity由头区和体组成,虽然一些response只包含头区。

在这个段中,发送者和接收者可以是clientserver,看谁发送和接收实体。

71实体头区

定义了实体的描述数据,如果没有实体,那就是request指定资源的描述数据。一些是可选的,一些是必须的。

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

扩展头区机制允许额外的头区定义而不用改变协议,但是这些区并不能假定会被接收者识别出。没有识别的要被接收者忽略而且必须被透明proxy传递。

7.2 Entity Body

它是以实体头区定义的形式和编码形成的伴随requestresponse发送的。

entity-body = *OCTET

一个Entity Body只存在于一个存在消息体的消息中,(sec4.3)。通过解码传输编码从message-body中得到entity-body

721类别

当一个entity-body被一个消息包含时,通过头区Content-TypeContent-Encoding决定类型。这些定义了一个两层的 有序的编码模型。

entity-body := Content-Encoding( Content-Type( data ) )

Content-Type声明了数据的类型。Content-Encoding用来给出额外的内容编码,通常是用来数据压缩的,是被request资源的属性。没有默认的编码。

任何包含一个实体的HTTP/11消息应该包含一个Content-Type头区来定义那个体的media type。如果media type没有在一个content-type区被给出,接收着可以通过内容或uri的名字扩展来猜。如果还是未知,那就应该作为application/octetstream

722 实体长度

即使消息体被任何传输编码应用前的长度。Sec4.4定义了怎么确定一个消息体的传输长度。

8 连接

81持久连接

811目的

持久连接之前,一个单独的TCP连接需要每次取得URL来建立,增大了HTTP server的负载并且引起internet的拥挤。使用联机图片和其他相关数据资源通常要求一个client在极短时间向相同的server发送多个request。关于这些性能问题的分析和对一个实验性实现的结果是可用的[26][30]。实现经验和实际的HTTP/11RFC2068)的测量显示了很好的结果。也产生了可选的代替,例如,T/TCP[27]

持久的HTTP连接有很多优点:

l         打开和关闭更少的TCP连接,节省了通讯链路上路由器和主机(clients,servers,proxies,gateways,tunnels,caches)上的CPU消耗,也节省了主机上对TCP控制块的内存消耗

l         HTTP连接和请求可以在一次连接上pipeline。这允许一个client发送多个request而不用等response,允许单个TCP连接被更有效地使用而节省了大量时间。

l         网络拥塞被降低了,因为减少了TCP打开的PACKETS,和允许TCP有更多的时间决定网络拥挤状态

l         等待下一个request时间被降低了,应为可以花费更少的时间在TCP握手上

l         HTTP可以更好地发展,因为错误在不关闭TCP连接的情况下被报告。HTTP的未来版本的client可以乐观地使用一个新特征,但是要和一个旧server通讯就要在错误被报告时尝试旧语义。

HTTP应用应该实现持久连接。

812整体流程

HTTP/11和其他早期HTTP的重要区别就是持久化连接是所有HTTP连接的默认连接。也就是,除非有另外指明,client应该假定server保持一个持久连接,即使server发送一个error

持久化连接提供了一个机制,通过它一个client和一个server能够表示tcp连接的关闭,就是使用connection 头区。一旦一个close被标记,client不能在connection上发送任何request

8121 Negotiation

一个HTTP/11server可以假定一个HTTP/11client想要保持一个持久化连接直到一个connection区被指定为“close”,并且被以request发送。如果server想在response之后关闭连接,它应该这样指明。

一个HTTP/11client可以期待连接保持,但是通过responseconnection头区来决定是否保持;而如果不想连接保持,就应该发一个closeconnection头区。

如果clientserver有一个发了,那么request是连接的最后一个。

Clientserver不应该假定低于HTTP11的版本会维持一个持久化连接。Sec19.6.2提供更多兼容信息。

为了保持持久,所有在连接中的消息必须有一个自定义的消息长度,sec4.4

8122流水线

一个支持持久化连接的client可以流水它的request(也就是说,发送多个request而不必等待response)。一个server必须发送它的response给那些requestrequest应该接收到的顺序。

Client在连接建立后马上假定持久化连接和流水线存在的如果第一次流水线试图失败要准备重新建立连接。如果一个client做这样的重试,它在知道连接是持久化之前绝对不能pipeline。如果server在发送所有对应response之前关闭连接,client也必须要准备重发所有的请求。

Client不应该发送非等幂(或序列)方法的request。否则一个运输连接的过早终结可能会导致结果的不确定。一个希望发送一个非等幂requestclient应该等到前一个request对应的response到了后再发。

813代理服务器

proxy正确实现connection头区(sec14.10)的属性是非常重要的。

Proxy必须分别给它的clientorigin server(或其他proxy server)标记持久化连接。每一个持久化连接对应一个链。

一个proxy绝对不能建立HTTP/11持久连接和一个HTTP/10client(RFC2068)

814实践考虑

server通常有一些超时值,超过了这些值就不会维持一个活动连接。Proxy可以设得更高因为可能一个client可能会和它r做更多的连接。这个值本身的大小没有限制。

当一个clientserver想要超时,它应该给那个连接发一个优美的中断。Clientserver都应该经常地观察传输的另一端,合适地给以处理。如果相反的话会导致网络资源耗尽。

一个client,serverproxy可以在任何时候关闭传输连接。例如,一个client会开始发送一个新的request同时一个server决定关闭这个看似空闲的连接。从server的角度看,连接就要被关闭,从client的角度看,一个request正在被发送。

这意味着client ,server,proxy必须能够从异步关闭事件中恢复。Client软件应该从新打开连接从新发送失败的request,只要request序列是等幂的(sec9.1.2)就不需要用户交互。不等幂的方法或序列绝对不能被自动重发,虽然user agent可以提供一个手工操作来选择重新发送。User-agent软件的确认回代替用户的确认。如果第2次请求序列失败自动重发不应该继续。

Server应该总是对一个连接至少发一个response,如果可能的话。Server不应该在发送一个response的过程中关闭一个连接,除非预测到一个网络连接或client失败。

使用持久连接的client应该限制他们维持到同一个server的并行连接数。一个单个的user client不应该对任何serverproxy保持对于2个连接。一个proxy应该使用最多2*N个连接到另一个serverproxyN是同时活跃的users个数。这些原则被用来提高http response时间并且避免拥塞。

82消息传送要求

821持久连接和流控制

HTTP/1.1server应该保持持久连接并且使用TCP的流控制机制来解决临时过载的问题,而不是知道clientretry还终止连接。后者会加重网络租塞。

8.2.2 监视连接中的错误状态信息

一个HTTP/11(或之后的)正在发送消息体的 client当它正在传递request时应该监视网络连接的错误状态。如果client看到一个错误状态,它应该迅速终止消息体的发送。如果正在用“chunked”(sec3.6)编码发送,一个0长度的chunk和空尾部可以被使用用来标志消息的结束。如果消息体先于一个Content-Length头部,client必须关闭连接。

8.2.3使用100status

100状态的存在是为了允许一个正在发送带bodyrequest messageclient来决定是否一个origin server想要接收request(基于request header),这发生在实际发送request body之前。在某些情况下,发送一个不被server看就拒绝的消息体是不合适和浪费效率的。

HTTP/11client的要求:

。如果一个client愿意在发送一个request body前等待100response,它必须发送一个期待100的头区。

。一个client决不能发送一个期待100的头区如果它不想发request body

由于更老板本的存在,协议允许一个client发了期待100头区后没有受到417100。因此,一个client发了期待100头区后就不应该无限等待request

HTTP/11server的要求:

l         当接收到一个包含expect 100-continue”头区的request时,origin server必须要么一100Continue)状态返回并且继续从输入流中读,要么返回一个终止状态编码。Origin server 绝对不能在发送100response之前等待request body。如果它返回一个终止状态,它可以关闭连接或可以继续读但放弃request的剩余部分。它决不能执行request的方法如果它返回一个终止符。

l         一个origin server不应该发送一个100continueresponse,如果request 消息没有包含expect 100-continue”头区,并且也绝对不能发送这样的response如果request是来自一个HTTP/10(或更早版本的)client。有一个意外:为了和RFC2068兼容,一个server可以发送一个100状态在response中给一个HTTP/11putpost request,尽管没有包含expect 100-continue”头区。这个异常,只适用于HTTP/11request,并不适用于其他HTTP版本,目的就是减少client的等待时间。

l         一个origin server可以可以忽略100如果它已经接收到一些或全部的request body.

l         一个发送了一个100origin server必须在收完body并且处理后发送一个final status code,除非它过早地终止连接。

l         如果一个origin server接收到一个未包含Expect 100头区的request,而又包含一个bodyserver在从连接读整个body前回以一个final status,那么server不应该关闭连接直到它读了整个request或直到client关闭了连接。否则,client不能可靠地接收response。然而,这个要求并不是说保护server免受服务拒绝攻击或错误的client实现。

HTTP/11proxy的要求:

。如果一个代理接收到一个包含100期待的头区的request,代理要么知道要么不知道下一个serverHTTP11的兼容,它必须转发request,包括expect头区。

。如果proxy知道下一个server 支持http/1.0或更低,它决不能转发,而必须发挥417

Proxy应该维护一个关于最近接收的下一个serverHTTP版本号的缓存。

。一个proxy决不能返回100response给一个HTTP/10client(不包含100-continue期待)。这个请求覆盖了转发1xx response的规则。

824 clientserver过早关闭连接后的行为

如果一个HTTP/11client发送一个包含bodyrequest,但是没有包含100头区期待,而且并不是直接连HTTP/11origin server,而且看到了从server过来的连接关闭,应该重试request。如果重试,它可以采用下面的2等幂算法来确保得到可靠连接:

1.  初始化一个到server的新连接

2.  发送request-headers

3.  初始化一个R,来存放到server 的来回是,如果不可得就设置成5s

4.  计算T=R*2**N),N是之前尝试重发的次数。

5.  等一个错误responseTs

6.  如果没有接收到error responseTs后发送requestbody

7.  Client看到连接被过早关闭,重复1步直到request被接收,或收到一个错误response,或client不耐烦关闭了尝试进程。

在任何错误状态被接收的点,client

l         不应该继续

l         应该关闭连接如果还没有完成发送request message


只有注册用户登录后才能发表评论。


网站导航: