Skip to content

Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing

1. Introduction

超文本传输协议(HTTP)是一种无状态的应用层请求/响应协议,使用可扩展的语义和自描述的消息负载与基于网络的超文本信息系统进行灵活的交互。本文档是 HTTP/1.1 规范的一部分,涵盖了消息语法和路由。

2. Architecture

2.1. Client/Server Messaging

HTTP 是一个无状态的请求/响应协议,通过可靠的传输层或会话层“连接”来交换消息。HTTP 客户端是一个程序,它建立与服务器的连接以发送一个或多个 HTTP 请求。HTTP 服务器是一个程序,它接受连接以通过发送 HTTP 响应来处理 HTTP 请求。

2.2. Implementation Diversity

HTTP 的实现多种多样,包括家用电器、立体声设备、固件更新脚本、命令行程序、移动应用等。不同的用户代理可能无法与用户交互或提供足够的安全或隐私警告。

2.3. Intermediaries

HTTP 支持通过代理、网关和隧道等中介来满足请求。中介可以在用户代理和原始服务器之间传递消息。

2.4. Caches

缓存是本地存储的先前响应消息及其控制子系统。缓存存储可缓存的响应,以减少未来等效请求的响应时间和网络带宽消耗。

2.5. Conformance and Error Handling

本规范根据 HTTP 通信中参与者的角色定义一致性标准。发送者不得生成已知为错误的协议元素,接收者必须能够解析适用于其角色的协议元素。

2.6. Protocol Versioning

HTTP 使用“<major>.<minor>”编号方案来表示协议版本。HTTP/1.1 消息的版本通过消息的第一行中的 HTTP-version 字段来指示。

2.7. Uniform Resource Identifiers

统一资源标识符(URI)用于 HTTP 中标识资源。HTTP 定义了“http”和“https”URI 方案。

2.7.1. http URI Scheme

“http”URI 方案用于根据潜在 HTTP 原始服务器监听给定端口的层次命名空间来铸造标识符。

2.7.2. https URI Scheme

“https”URI 方案用于根据潜在 HTTP 原始服务器监听 TLS 安全连接的给定端口来铸造标识符。

2.7.3. http and https URI Normalization and Comparison

“http”和“https”方案遵循 URI 通用语法,并根据 RFC 3986 的算法进行规范化和比较。

3. Message Format

所有 HTTP/1.1 消息由一个起始行、若干个头字段、一个空行和一个可选的消息体组成。

3.1. Start Line

HTTP 消息可以是从客户端到服务器的请求或从服务器到客户端的响应。两者的起始行格式不同,分别是请求行和状态行。

3.1.1. Request Line

请求行以方法标记开始,后跟请求目标和协议版本。

3.1.2. Status Line

状态行包含协议版本、状态码和描述状态码的文本原因短语。

3.2. Header Fields

每个头字段由不区分大小写的字段名、冒号、可选的前导空白、字段值和可选的尾随空白组成。

3.3. Message Body

HTTP 消息的消息体用于携带请求或响应的有效负载。消息体的存在由 Content-Length 或 Transfer-Encoding 头字段指示。

3.4. Handling Incomplete Messages

处理不完整的消息时,服务器可以在关闭连接之前发送错误响应。客户端必须记录不完整的响应消息。

3.5. Message Parsing Robustness

服务器在解析请求行时应忽略接收到的至少一行空行。接收者可以将单个 LF 识别为行终止符。

4. Transfer Codings

传输编码用于指示为确保通过网络的“安全传输”而应用于有效负载体的编码转换。

4.1. Chunked Transfer Coding

分块传输编码将有效负载体包装为一系列带有大小指示的分块,最后可能跟随一个包含头字段的可选拖尾。

4.2. Compression Codings

定义了几种用于压缩消息有效负载的编码格式,如 compress、deflate 和 gzip。

4.3. TE

TE 头字段指示客户端愿意接受的传输编码以及是否接受分块传输编码中的拖尾字段。

4.4. Trailer

当消息包含分块传输编码的消息体时,发送者应生成 Trailer 头字段以指示将在拖尾中出现的字段。

5. Message Routing

HTTP 请求消息的路由由客户端根据目标资源、客户端的代理配置和入站连接的建立或重用来确定。

5.1. Identifying a Target Resource

HTTP 通信由用户代理为某些目的发起,通常使用 URI 引用作为目标资源的标识符。

5.2. Connecting Inbound

客户端确定目标 URI 后,需要决定是否需要网络请求以及请求的目标位置。

5.3. Request Target

请求目标有四种不同的格式,取决于请求的方法和请求是否通过代理。

5.3.1. origin-form

最常见的请求目标形式是 origin-form,包含绝对路径和可选的查询组件。

5.3.2. absolute-form

当向代理发送请求时,客户端必须使用绝对形式的目标 URI。

5.3.3. authority-form

authority-form 仅用于 CONNECT 请求。

5.3.4. asterisk-form

asterisk-form 仅用于服务器范围的 OPTIONS 请求。

5.4. Host

Host 头字段提供目标 URI 中的主机和端口信息,使原始服务器能够区分资源。

5.5. Effective Request URI

服务器根据请求目标、Host 头字段和连接上下文重构预期的目标 URI。

5.6. Associating a Response to a Request

HTTP 依赖响应到达的顺序与同一连接上请求的顺序完全一致。

5.7. Message Forwarding

中介在转发消息时必须实现 Connection 头字段,并排除仅用于入站连接的字段。

5.7.1. Via

Via 头字段指示用户代理和服务器之间的中介协议和接收者。

5.7.2. Transformations

某些中介包含转换消息及其有效负载的功能。

6. Connection Management

HTTP 消息独立于底层传输层或会话层连接协议。HTTP 仅假设可靠的传输和按顺序交付的请求和响应。

6.1. Connection

Connection 头字段允许发送者指示当前连接的控制选项。

6.2. Establishment

连接的建立超出了本规范的范围,每个连接仅适用于一个传输链接。

6.3. Persistence

HTTP/1.1 默认使用持久连接,允许在单个连接上传输多个请求和响应。

6.3.1. Retrying Requests

连接可以随时关闭,客户端可以在连接关闭后自动重传中止的请求序列。

6.3.2. Pipelining

支持持久连接的客户端可以“流水线化”其请求,即在等待每个响应之前发送多个请求。

6.4. Concurrency

客户端应限制其与给定服务器保持的同时打开连接的数量。

6.5. Failures and Timeouts

客户端、服务器或代理可以随时关闭传输连接。

6.6. Tear-down

Connection 头字段提供了“close”连接选项,指示发送者希望在当前请求/响应对完成后关闭连接。

6.7. Upgrade

Upgrade 头字段用于在同一连接上从 HTTP/1.1 过渡到其他协议。

7. ABNF List Extension: #rule

ABNF 规则的 #rule 扩展用于改进某些头字段值定义的可读性。#rule 用于定义逗号分隔的元素列表。

ABNF

BWS = OWS

Connection = *( "," OWS ) connection-option *( OWS "," [ OWS connection-option ] )

Content-Length = 1*DIGIT

HTTP-message = start-line *( header-field CRLF ) CRLF [ message-body ]
HTTP-name = %x48.54.54.50 ; HTTP
HTTP-version = HTTP-name "/" DIGIT "." DIGIT
Host = uri-host [ ":" port ]

OWS = *( SP / HTAB )

RWS = 1*( SP / HTAB )

TE = [ ( "," / t-codings ) *( OWS "," [ OWS t-codings ] ) ]
Trailer = *( "," OWS ) field-name *( OWS "," [ OWS field-name ] )
Transfer-Encoding = *( "," OWS ) transfer-coding *( OWS "," [ OWS transfer-coding ] )

URI-reference = <URI-reference, see [RFC3986], Section 4.1>
Upgrade = *( "," OWS ) protocol *( OWS "," [ OWS protocol ] )

Via = *( "," OWS ) ( received-protocol RWS received-by [ RWS comment ] ) *( OWS "," [ OWS ( received-protocol RWS received-by [ RWS comment ] ) ] )

absolute-URI = <absolute-URI, see [RFC3986], Section 4.3>
absolute-form = absolute-URI
absolute-path = 1*( "/" segment )
asterisk-form = "*"
authority = <authority, see [RFC3986], Section 3.2>
authority-form = authority

chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
chunk-data = 1*OCTET
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token / quoted-string
chunk-size = 1*HEXDIG
chunked-body = *chunk last-chunk trailer-part CRLF
comment = "(" *( ctext / quoted-pair / comment ) ")"
connection-option = token
ctext = HTAB / SP / %x21-27 ; '!'-'''
 / %x2A-5B ; '*'-'['
 / %x5D-7E ; ']'-'~'
 / obs-text

field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-name = token
field-value = *( field-content / obs-fold )
field-vchar = VCHAR / obs-text
fragment = <fragment, see [RFC3986], Section 3.5>

header-field = field-name ":" OWS field-value OWS
http-URI = "http://" authority path-abempty [ "?" query ] [ "#" fragment ]
https-URI = "https://" authority path-abempty [ "?" query ] [ "#" fragment ]

last-chunk = 1*"0" [ chunk-ext ] CRLF

message-body = *OCTET
method = token

obs-fold = CRLF 1*( SP / HTAB )
obs-text = %x80-FF
origin-form = absolute-path [ "?" query ]

partial-URI = relative-part [ "?" query ]
path-abempty = <path-abempty, see [RFC3986], Section 3.3>
port = <port, see [RFC3986], Section 3.2.3>
protocol = protocol-name [ "/" protocol-version ]
protocol-name = token
protocol-version = token
pseudonym = token

qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'['
 / %x5D-7E ; ']'-'~'
 / obs-text
query = <query, see [RFC3986], Section 3.4>
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )

quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE

rank = ( "0" [ "." *3DIGIT ] ) / ( "1" [ "." *3"0" ] )
reason-phrase = *( HTAB / SP / VCHAR / obs-text )
received-by = ( uri-host [ ":" port ] ) / pseudonym
received-protocol = [ protocol-name "/" ] protocol-version
relative-part = <relative-part, see [RFC3986], Section 4.2>
request-line = method SP request-target SP HTTP-version CRLF
request-target = origin-form / absolute-form / authority-form / asterisk-form

scheme = <scheme, see [RFC3986], Section 3.1>
segment = <segment, see [RFC3986], Section 3.3>
start-line = request-line / status-line
status-code = 3DIGIT
status-line = HTTP-version SP status-code SP reason-phrase CRLF

t-codings = "trailers" / ( transfer-coding [ t-ranking ] )
t-ranking = OWS ";" OWS "q=" rank
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
token = 1*tchar
trailer-part = *( header-field CRLF )
transfer-coding = "chunked" / "compress" / "deflate" / "gzip" / transfer-extension
transfer-extension = token *( OWS ";" OWS transfer-parameter )
transfer-parameter = token BWS "=" BWS ( token / quoted-string )

uri-host = <host, see [RFC3986], Section 3.2.2>