4.HTTP 消息
4.1消息类型
HTTP消息由客户端发到服务器端的request和相反方向的response组成。
HTTP-message = Request | Response ; HTTP/1.1 messages
Request(sec5)和response(sec6)消息使用RFC822[9]的通用消息格式来传递实体(message的有效负荷)。由一个开始行,0或多个头区(头部),一个空行(在CRLF前什么也没有)来指示头区结束,和一个可能的body。
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line
为了保持健壮性,服务器应该在Request-Line被期待的地方忽略任何空行。换句话说,如果服务器在消息的开始读协议流,首先接收了一个CRLF,它应该忽略crlf。
某些臭虫很多的HTTP/1。0client实现产生额外的CRLF在一个POSTrequest后。重申一下在 BNF处的禁令,一个HTTP/1。1client绝对不能在一个request的前后加CRLF。
4.2消息头
HTTP头区,包含general-header (section 4.5), request-header (section 5.3), response-header
(section 6.2), 和 entity-header (section 7.1) fields,遵从通用的格式定义(sec3.1RFC822[9])。每一个头区由一个名字跟着一个:和一个区值组成。区名是大小写不敏感的。区值可以一任何数目的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取代之。
不同区名的头区出现顺序不相同也没有关系。但是,最好首先发送通用头区,然后是request或response头区,以entity-header头区结束。
在一个消息中可以出现多头区对应同一个区名,只要对那个头区的头区值是可以用逗号分隔的列表。必须可能把多个头区合并成“name:value”对而不改变语义。顺序是重要的,因为解释需要顺序,而且因此一个proxy绝对不能改变顺序。
4.3消息体
HTTP消息的消息体被用来携带跟随request和response的实体。消息体只在一个传输编码被使用时才和实体不同。
message-body = entity-body
| <entity-body encoded as per Transfer-Encoding>
当要保证消息被安全和合适传输时需要传输编码,Transfer-Encoding就是用来指示传输编码的。这是消息的一个属性,而不是实体的,因此可以在request/response链中被增加或删除。(但是,sec3.6增加了什么时候可以用这个属性)。
什么情况下确定消息中有一个消息体在request和response不同的。
Request是当包含Content-Length 或 Transfer-Encoding头区时有消息体。如果一个 request的方法定义中不允许一个消息体包含在消息中发送,那么就绝对不能。一个server应该读或传递一个消息中的消息体,而如果request中的方法定义中没有指示消息体,那就应该忽略过去。
对于response,有无则依赖于request的方法和response的状态码(sec6.1.1)。所有对应HEADrequest 方法的肯定没有,即使实体头区的存在可能让人相信它存在。所有的1xx,204和304也肯定没有。所有其它的一定有,即使它可能是0长度。
4.4消息长度
消息长度是指在传输编码使用后消息体的长度。当一个消息体被包含在一个消息中时,体长由下面决定(按优先级的顺序):
1. 任何肯定不包含一个消息体的response消息总是在第一个空行处终结,而无论出现在消息中的实体的头区。
2. 如果一个Transfer-Encoding头区(sec14.41)被给出而且只有”identity”,那么传输长度是使用“chunked”传输编码,直到连接被关闭消息被终结。
3. 如果一个Content-Length头区(sec14.13)被给出,那么它既代表了实体长度也代表了传输长度。如果这两个长度不相等肯定不会有Content-Length。如果一个消息既存在Transfer-Encoding又存在Content-Length,后者被忽略。
4.如果消息使用“multipart/byteranges”做媒体类型,并且transfer-length也没被给出,那么这个自定界的媒体类型定义了传输长度。这个类型如果接收者无法解析它那肯定不能被使用;在一个request中,如果包含一个Range头和若干byte-range说明那个client能够解析multipart/ranges。一个rang头可能被一个不理解multipart/byteranges的proxy传递,在这种情况下,server必须使用1,3,5提供的方法定界。
5.到server关闭一个连接(关闭连接不能被用来指示一个request的结束,因为那样将导致server无法发送一个response。)
为了和HTTP/1。0应用兼容,包含一个消息体的。1请求肯定包含一个有效的Content-Length
除非知道server是HTTP/1。1兼容。如果一个request包含一个消息体而没有
Content-Length,那么server如果不能决定消息的长度应该回以400,或411如果它坚持接收一个有效Content-Length。
所有接收实体的HTTP/1。1应用必须接收“chunked”传输编码(sec3.6),因此允许使用这个机制决定消息长度。
消息绝对不能同时包含Content-Length头区和一个非identity传输编码。如果一定包含,那么Content-Length被忽略。
如果一个Content-Length真被给出了,那 它一定对应消息体的字节个数。HTTP/1。1user agent必须告诉用户如果一个无效长度被接受和看到。
4.5通用头区
有一些头区在request和response中通用,但是不能用于被传输的实体。这些头区只用于被传递的消息。
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
通用头区的名字可以跟随一个改变的版本号而被扩展。但是,新的或实验的头区可以被给通用头区的语义如果通讯双方都认同。认不出的头区被认为是实体头区。