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>