Skip to main content

4. HTTP Message (HTTP消息)

4.1 Message Types (消息类型)

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

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

请求(第 5 节)和响应(第 6 节)消息使用 RFC 822 [9] 的通用消息格式来传输实体(消息的有效负载)。两种类型的消息都由起始行、零个或多个头字段(也称为 "headers")、指示头字段结束的空行(即,在 CRLF 之前没有任何内容的行)以及可能的消息主体组成。

generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line

为了健壮性,服务器应该 (SHOULD) 忽略在期望 Request-Line 的位置接收到的任何空行。换句话说,如果服务器在消息开始时读取协议流并首先接收到 CRLF,它应该忽略该 CRLF。

某些有缺陷的 HTTP/1.0 客户端实现在 POST 请求后生成额外的 CRLF。重申 BNF 明确禁止的内容,HTTP/1.1 客户端禁止 (MUST NOT) 在请求前或请求后添加额外的 CRLF。

4.2 Message Headers (消息头)

HTTP 头字段,包括通用头 (general-header)(第 4.5 节)、请求头 (request-header)(第 5.3 节)、响应头 (response-header)(第 6.2 节)和实体头 (entity-header)(第 7.1 节)字段,遵循与 RFC 822 [9] 第 3.1 节中给出的相同的通用格式。每个头字段由一个名称后跟冒号(":")和字段值组成。字段名称不区分大小写。字段值可以 (MAY) 在前面加上任意数量的 LWS,尽管首选单个 SP。头字段可以通过在每个额外行之前加上至少一个 SP 或 HT 来扩展到多行。应用程序在生成 HTTP 构造时应该 (ought to) 遵循 "通用形式" (common form)(如果已知或指示的话),因为可能存在一些无法接受超出通用形式的任何内容的实现。

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:在 field-value 的第一个非空白字符之前或最后一个非空白字符之后出现的线性空白。可以 (MAY) 删除这样的前导或尾随 LWS 而不改变字段值的语义。在 field-content 之间出现的任何 LWS 都可以 (MAY) 在解释字段值或向下游转发消息之前替换为单个 SP。

接收具有不同字段名称的头字段的顺序不重要。但是,首先发送通用头字段、然后是请求头或响应头字段、最后以实体头字段结束是 "良好实践" (good practice)。

当且仅当该头字段的整个 field-value 被定义为逗号分隔列表 [即 #(values)] 时,消息中可以 (MAY) 存在具有相同 field-name 的多个 message-header 字段。必须 (MUST) 可以将多个头字段组合成一个 "field-name: field-value" 对,而不改变消息的语义,方法是将每个后续 field-value 附加到第一个,每个用逗号分隔。因此,接收具有相同 field-name 的头字段的顺序对于组合字段值的解释很重要,因此代理禁止 (MUST NOT) 在转发消息时更改这些字段值的顺序。

4.3 Message Body (消息主体)

HTTP 消息的 message-body(如果有)用于携带与请求或响应相关联的 entity-body。仅当应用了传输编码 (transfer-coding) 时,message-body 才与 entity-body 不同,如 Transfer-Encoding 头字段(第 14.41 节)所示。

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

必须 (MUST) 使用 Transfer-Encoding 来指示应用程序为确保消息的安全和正确传输而应用的任何传输编码。Transfer-Encoding 是消息的属性,而不是实体的属性,因此可以 (MAY) 被任何中间应用程序添加或删除。

当 message-body 存在于消息中时,由第 4.4 节中定义的规则确定 message-body 的传输长度。

4.4 Message Length (消息长度)

消息的传输长度是 message-body 在传输中出现的长度。当 message-body 存在于消息中时,该主体的传输长度由以下之一确定(按优先顺序):

  1. 任何不得 (MUST NOT) 包含 message-body 的响应消息(例如 1xx、204 和 304 响应以及对 HEAD 请求的任何响应)始终由头字段后的第一个空行终止,无论消息中存在哪些实体头字段。

  2. 如果存在 Transfer-Encoding 头字段且不是 "identity",则传输长度由 "chunked" 传输编码定义,除非消息通过关闭连接来终止。

  3. 如果存在 Content-Length 头字段(第 14.13 节),则其十进制值以八位字节表示 Entity-Length 和 transfer-length。如果这两个长度不同(即,存在 Transfer-Encoding 头字段),则禁止 (MUST NOT) 发送 Content-Length 头字段。(注意:某些较旧的实现错误地发送了 Content-Length 和 non-identity Transfer-Encoding。)

  4. 如果消息使用媒体类型 "multipart/byteranges",并且未以其他方式指定 transfer-length,则此自定界媒体类型定义 transfer-length。除非发送方知道接收方可以解析它,否则禁止 (MUST NOT) 使用此媒体类型;接收方存在 Range 头字段表示客户端可以解析 multipart/byteranges 响应。

    一个范围头字段可能由不理解 multipart/byteranges 的 HTTP/1.0 代理转发;在这种情况下,服务器必须 (MUST) 用 Content-Range 字段分隔消息。

  5. 通过服务器关闭连接。(关闭连接不能用于指示请求主体的结束,因为这会使服务器无法发送回响应。)

为了与 HTTP/1.0 应用程序兼容,包含 message-body 的 HTTP/1.1 请求必须 (MUST) 包含有效的 Content-Length 头字段,除非已知服务器符合 HTTP/1.1。如果请求包含 message-body 并且不包含 Content-Length,则如果服务器无法确定消息的长度,它应该 (SHOULD) 以 400(bad request)响应;或者如果服务器坚持接收有效的 Content-Length,则以 411(length required)响应。

所有 HTTP/1.1 应用程序必须 (MUST) 接受请求消息中的 "chunked" transfer-coding,即使应用程序本身不发送分块消息。如果 HTTP/1.1 请求包含 message-body 但不包含 Content-Length,服务器应该 (SHOULD) 响应 400(bad request),如果它无法确定请求的长度,或者响应 411(length required),如果它希望坚持接收有效的 Content-Length。

如果请求包含 message-body 并且未给出 Content-Length,服务器应该 (SHOULD) 以 400(bad request)响应,如果它无法确定消息的长度,或者以 411(length required)响应,如果它希望坚持接收有效的 Content-Length。

消息不应该 (SHOULD NOT) 包括 Transfer-Encoding 和 Content-Length 头字段。如果消息确实包括这两者,Transfer-Encoding 必须 (MUST) 删除 Content-Length。

当接收到并解析了内容编码实体,如果已知内容编码,message-body 长度由解码后的数据确定。

4.5 General Header Fields (通用头字段)

有一些头字段具有通用适用性,适用于请求和响应消息,但不适用于正在传输的实体。这些头字段仅适用于正在传输的消息。

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

通用头字段名称只能通过更改协议版本来可靠地扩展。但是,可以在不更改协议版本的情况下为字段值赋予新的或实验性的头字段。第 7.1 节定义了实体头字段的语义。

无法识别的头字段应该 (SHOULD) 被接收方视为实体头字段。