HTTP/1.1 协议 4-7

来源:互联网 发布:seo和sem 编辑:程序博客网 时间:2024/05/20 11:33

4 HTTP 消息

4.1 消息类型

HTTP消息由客户端到服务端的请求和服务端到客户端的响应组成。

HTTP-message = Request | Response ; HTTP/1.1 messages

请求和响应信息使用RFC 822 [9]中的通用消息格式来传输实体(消息有效载荷)。两种消息都有一个开始行、零或多个报头域(也被成为报头headers)、一个指定报头域结束的空行以及一个可能的消息主体。

generic-message = start-line

*(message-header CRLF)

CRLF

[ message-body ]

start-line = Request-Line | Status-Line

为了保持鲁棒性,服务段在获取请求行(Request-Line)时应该(SHOULD)忽略接收到的空行,换句话说,如果服务正在信息开始时读取协议流,那么它应该忽略最先接收到的CRLF。一些有缺陷的HTTP/1.0客户端实现会在POST请求之后产生额外的CRLF。需要重复一下,BNF所明确禁止的是,HTTP/1.1绝对不能(MUST NOT)在请求的前后有额外的CRLF

 

4.2消息报头( Message Headers)

HTTP报头域包括e general-header (section 4.5), request-header (section 5.3), response-header

(section 6.2)entity-header (section 7.1)等域,都遵循RFC 822 [9]3.1章所给出的通用格式。每个报头域有一个名字和一个紧随其后的“:”以及域值组成。域名字不区分大小写。域值可以(MAY)以任意数目的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>

field-content不包括开头和结尾LWS:出现在域值非空格字符前后的空白。这些开头或结尾的LWS可以在不改变域值语义的前提下删除。任何出现在field-content之间的LWS可以在解释区值或转向消息流前替换为一个SP。不同域名的报头域的次序并不重要。但是,最好首先发送通用报头域,其次发送请求报头域或者响应报头域,最后发送实体报头域。

只有对应报头域的全部域值被定义为一个逗号分隔的列表时,相同域名的多个消息报头域肯能会出现在一个消息里[例如#(values)]。必须可能把多个报头域合并成“field-name: field-valu”对而不改变语义,通过向第一个field-value追加后续的值,这些值由一个“,”来间隔。

由于需要解释组合的域值,所接收的同一域名的报头域的次序是重要的,同样的原因代理不能更改消息投递时域值的顺序。

4.3 消息体(Message Body)

HTTP信息的消息体(如果有)是用来传送请求或响应的实体主体。消息体与实体主体的唯一区别在于是否进行传输编码,编码由传输编码(Transfer-Encoding)域来指定(14.41章)。.

message-body = entity-body

| <entity-body encoded as per Transfer-Encoding>

传输编码必须(MUST)用来指定一些传输编码来由应用程序来确保消息安全与恰当的传输。传输编码是消息而不是实体的属性,因此它可以(MAY)被请求/响应链里的应用增加或者删除。。(但是,3.6章对何时使用什么样的传输编码做出了限制)。

消息里是否有消息体的规则对请求和响应是不同的。

请求的消息头里的Content-Length或者Transfer-Encoding报头域决定了在请求里是否存在消息体。如果文档规定了请求方法不能发送实体主体,那么请求中就不能有消息体。服务端应该对所有消息读取和传递消息体;如果请求方法中不包括对实体主体的定义,处理请求时应该忽略消息体。

对响应消息而言,消息是否有消息体取决于请求方法和响应状态嘛(6.1.1章)。HEAD请求方法的响应不能有消息体,尽管会有实体报头域来表明已经处理过了。所有1xx(报告),204(无内容)和304(无修改)响应不能包含消息体。其他的所有响应需要包含消息体,不过可以是零长度的。

4.4 消息长度(Message Length)

消息的传输长度是指消息体出现在消息里的长度;换句话说是消息经过传输编码后的长度。如果消息包括消息体,那么主体的长度是由以下条件中的一个决定的(顺序优先)

1.        不包含消息体的响应消息(若1xx204304响应以及对HEAD请求的响应)通常在报头域后的第一个空行停止读取,进而忽略出现在消息里的实体报头域。

2.        如果存在传输编码报头(14.41章)域并且报头值不为“identity”,传输长度由传输编码“chunked”定义,直到因连接关闭而终止消息。

3.        如果出现Content-Length报头域(14.13章),那么其数值应表示实体和传输长度。如果两者的传毒不一致,那么Content-Length不能被发送(已存在Transfer-Encoding报头域)。如果接收到的消息存在Transfer-Encoding和Content-Length,后者必须被忽略。

4.        如果消息使用媒体类型“multipart/byteranges”并且传输长度没有单独指定,那么由自定界限的媒体类型定义传输长度。媒体类型只能在发送者知道接收者可以解析它的情况下才能使用;1.1客户端请求里出现有分块byte-range指定的Range报头域意味着客户端能够解析multipart/byteranges响应。

不识别multipart/byteranges的1.0代理应该继续推送range报头;同时服务短必须使用本章1,3或者5中定义的方法来确定消息的界限。

5.        通过服务端关闭连接。(连接不能用来指定请求主体的结束,这样会导致服务端无法发回响应。)

为了兼容HTTP1.0应用,拥有消息体的HTTP1.1请求必须包括一个有效的Content-Length报头域,除非知道服务端兼容HTTP/1.1。如果含有消息体的请求没有给出Content-Length,而服务端无法判断消息长度,那么应该返回400(错误请求)响应,或者返回411(需要长度)来表明需要一个有效的Content-Length

所有HTTP/1.1应用接收实体时必须接受“chunked”传输编码(3.6章),借此在不能提前获知消息长度的时候使用此机制。

如果有消息体的消息里已经给出Content-Length,它的域值必须与消息体里的OCTET相匹配。HTTP/1.1用户代理在接收到一个无效的长度时必须通知用户。

4.5通用报头域(General Header Fields)

有一部分报头域对请求和响应有通用性,但是不适应于传递中的实体。这些报头域只使用于传输中的消息。

general-header = Cache-Control ; Section 14.9章

| Connection ;  14.10章

| Date ;  14.18章

| Pragma ;  14.32章

| Trailer ;  14.40章

| Transfer-Encoding ;  14.41章

| Upgrade ;  14.42章

| Via ;  14.45章

| Warning ;  14.46章

通用报头域名字只能同协议版本的改变相结合来扩展。不过,新的或者实验性的报头域可能给予通用报头域的语义,只是这需要所有通讯参与者的承认。未被承认的报头域被作为实体报头域来对待。

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)

请求行以方法标识开始,随后是请求URI和协议版本,最后以CRLF结束。元素之间由SP字符隔开。除最后的CRLF序列外不允许出现CR或者LF

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

5.1.1方法(Method

方法标识指定了应用到请求URI指向的资源上的方法,该方法是大小写敏感的。

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报头域指定(14.7章)。响应的返回码也会通知客户端当前某个方法是否应用到资源上,因为允许方法的集合可以动态的修改。如果源服务端可以识别方法但请求资源不允许时,服务端应该返回状态码405(禁止的方法);如果源服务端不识别或实现该方法,则返回501(未实现)。通常的服务端都必须实现GETHEAD方法。其他的方法是可选的(OPTIONAL);不过上述方法如果被实现,它们必须具备9章所支出的语义。

5.1.2    请求URI(Request-URI)

请求URI是一个统一资源定位符,它指定了请求申请的资源。

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

四个选项取决于请求的性质。星号“*”表示请求不应用于特定的资源而是服务端本身,这也只能在方法不需要申请特定的资源时使用。下面是例子:

OPTIONS * HTTP/1.1

如果请求是发向代理的,绝对URI是必须的。代理要传递请求或者从一个有效缓存中返回响应。注意代理可能传递该请求到另外一个代理或者绝对URI指定的服务端。为了杜绝请求死循环,代理必须识别它所有的服务名,包括别名,本地变量和IP地址。下面是请求队列的例子:

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

为了能够是将来HTTP版本能够转换绝对URI,所有的HTTP/1.1服务端必须能够接受请求的绝对URI,尽管HTTP/1.1客户端只有来使用代理时才生成绝对URI

Authority形式只被CONNECT方法使用。(9.9)

最通用的请求URI形式是莫过于指定一个源服务或者网关的资源。这种情况下必须将URI的绝对路径作为请求URI传输,并且URI的网络地址URI(authority)必须在一个Host请求报头域里传输。例如一个客户端想要直接检索源服务上的资源,它需要创建一个到主机“www.w3.org ”80端口的TCP连接并发送以下队列:

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

Host: www.w3.org

后面跟着请求的剩余部分。注意绝对路径不能为空;如果最初的URI为空,那么必须作为“/”给出(服务根目录)。

请求URI按照3.2.1章支出的格式传输。如果请求使用“% HEX HEX”编码[42],源服务端必须解码请求URI以便于适当的解释请求。服务端应该对无效的请求URI返回适当的状态码。

透明代理在推送所接收请求URI时不能重写其“abs_path”部分,除非将上面所说的空路径替换为“/”。

注意:禁止重写规则是为了防止当源服务端使用错误的使用非保留字作为保留字时代理改变请求的含义。实现者应该注意到一些早期的HTTP/1.1代理会重写请求URI

5.2 (请求指定的资源)The Resource Identified by a Request

请求所指定的准确资源是由请求URIHost报头域共同决定的。

不使用请求的主机来区分资源的源服务端在确定HTTP/1.1请求指定的资源时可以忽略Host报头域。(但是请看一下HTTP/1.1所支持的其他Host需求)。

一个基于请求主机(有时候被称为虚拟主机或者虚拟主机名)区分资源的源服务端必须使用下面的规则来确定HTTP/1.1请求所请求的资源:

1.        如果请求URI是一个绝对URI,主机为请求URI中的主机名部分。请求中的哪些Host报头域值必须被忽略。

2.        如果请求URI不是一个绝对URI,并且请求包括一个Host报头域,那么主机由Host的域值来决定。

3.        如果由以上两种方法确定的主机是无效的,那么响应应该是一个400(错误的请求)错误信息。

缺少Host报头域的HTTP/1.0请求的接收者可以尝试使用启发式(例如检查URI路径看是否有针对特定主机的东西)的的方式来确定正确的请求资源。

5.3请求报头域(Request Header Fields)

请求报头域允许客户端向服务端传递关于请求及客户端自身的附件信息。这些字段相当于请求的修饰符,类似于编程语言中调用方法的参数。

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

请求报头域名字只能同协议版本的改变相结合来扩展。不过,新的或者实验性的报头域可能给予请求报头域的语义,只是这需要所有通讯参与者的承认。未被承认的请求报头域被作为实体报头域来对待。

6响应(Response

在接收并解释请求信息后,服务端返回HTTP响应信息。

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

6.1 状态行(Status-Line)

响应信息的第一行是状态行,依次由协议版本、数字状态码以及与之对应的文本组成,各元素间由空格(SP)分隔。除结尾的CRLF以外不允许出现CR或者LF。

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

6.1.1(状态码和原因分析)Status Code and Reason Phrase

状态码元素是一个三位证书码,表示请求是否被理解和满足。这些代码在第10章有详细的定义。原因分析是对状态码的简短的文本描述。状态码是用来自动处理,原因分析则是给人工用户处理的。客户端没有被强制要求去检查和显示原因分析。

状态码的首位定义了响应类别。后两位没有什么类别规则。首位数字有5种取值:

l         1xx:报告-接收请求,继续处理

l         2xx:成功-动作被成功接收、理解和接受。

l         3xx:重定向-为完成请求必须进行下一步动作。

l         4xx:客户端错误-请求有语法错误或者无法实现。

l         5xx:服务端错误-服务端无法实现一个显然有效的请求。

HTTP/1.0的状态代码、相应的原因解释例子在下面给出。这里给出的原因分析只是建议的——它们可以被修改而不会影响协议。

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应用可以不用理解所有注册的状态码,当然很显然理解更好。不过,应用应该理解状态码首位数字指示的类别,并将不识别的响应作为该类别的x00状态码进行处理。另外,不识别的响应不能缓存。例如,如果客户端收到一个不识别的状态码431,它可以明确的知道它的请求有错误然后像接收到一个400状态码那样处理响应。这种情况下,用户代理应将同响应一起返回的实体显示给用户,原因是实体里可能包括异常状态的解释信息。

6.2 响应报头域(Response Header Fields)

响应报头域允许服务端传递那些不能放在状态行里的信息。这些报头域给出了关于服务端和请求URI所指定资源访问情况的信息:

response-header = Accept-Ranges ; Section 14.5

| Age ; Section 14.6Z

| 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

响应报头域名字只能同协议版本的改变相结合来扩展。不过,新的或者实验性的报头域可能给予响应报头域的语义,只是这需要所有通讯参与者的承认。未被承认的报头域被作为实体报头域来对待。

.

7实体(Entity

 

请求和响应信息可能(MAY)传输实体,当然可能会由于请求方法或这响应状态码的限制而不传输实体由有实体报头域和实体主题组成,但一些响应可能只含有实体报头域。

从这个角度来看,客户端和服务端都能做为发送者或接收者,这取决于是谁来发送和接收实体。

7.1 实体报头域(Entity Header Fields)

实体报头域定义了有无实体主体,请求资源等元信息。这些元信息中有些是可选(OPTIONA)的,有些是在规范的部分环节中必须的(REQUIRED)。

entity-header = Allow ; 14.7章

| Content-Encoding ; 14.11章

| Content-Language ; 14.12章

| Content-Length ; 14.13章

| Content-Location ; 14.14章

| Content-MD5 ; 4.15章

| Content-Range ; 14.16章

| Content-Type ; 14.17章

| Expires ; 14.21章

| Last-Modified ; 14.29章

| extension-header

extension-header = message-header

扩展代理机制允许定义额外的实体报头域.而不必更改协议,但接收者可能不识别扩展的字段。接收者应该(SHOULD)忽略不能识别的报头域,透明代理则必须(MUST)将其继续推送。

7.2 实体主体(Entity Body)

HTTP请求或响应一起发送的实体主体(如果存在)的采用实体报头域定义的格式和编码方式。

entity-body = *OCTET

实体主体仅当消息实体存在的时候才会出现在消息中,具体描述请参看4.3章。

实体通过解码可能应用的任意传输编码来从消息主体中获取以保证安全和合适的消息传输。

7.2.1类型(Type

当消息里包括实体主体时,实体的数据类型由报头域Content-TypeContent-Encoding来决定。它们定义了一个两层的顺序的解码模型:

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

Content-Type指定了潜在数据的媒体类型。Content-Encoding可能用来指定应用到数据的附件的内容编码,一般是出于数据压缩的目的,那是请求资源的属性。这里没有默认编码

包含实体主体的HTTP/1.1/消息应该有一个Content-Type报头域来定义该主体的媒体类型。只有当Content-Typ报头域没有给粗媒体类型时,接收者可以尝试通过检查消息内容和(或者)指定资源的URI来推测媒体类型。如果还是不能知道媒体类型,接收者应该将其作为“application/octetstream”来处理。

7.2.2实体长度

消息的实体长度是指消息主体在为进行任何编码前的长度。

4.4章定义了消息主题的传输长度是如何决定的。

原创粉丝点击