3. Protocol Parameters (协议参数)
3.1 HTTP Version (HTTP版本)
HTTP 使用 "<major>.<minor>" 编号方案来指示协议的版本。协议版本策略旨在允许发送方指示消息的格式及其理解进一步 HTTP 通信的能力,而不是通过该通信获得的功能。对于不影响通信行为或仅添加到可扩展字段值的消息组件的添加,版本号不做任何更改。当对协议所做的更改添加的功能不改变一般消息解析算法,但可能添加到消息语义并暗示发送方的额外能力时,<minor> 数字递增。当协议内消息的格式发生更改时,<major> 数字递增。有关更完整的解释,请参见 RFC 2145 [36]。
HTTP 消息的版本由消息第一行中的 HTTP-Version 字段指示。
HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
注意,主版本号和次版本号必须 (MUST) 被视为单独的整数,并且每个版本号可以 (MAY) 递增到高于单个数字。因此,HTTP/2.4 是低于 HTTP/2.13 的版本,而 HTTP/2.13 又低于 HTTP/12.3。前导零必须 (MUST) 被接收方忽略,并且禁止 (MUST NOT) 发送。
发送包含 "HTTP/1.1" HTTP-Version 的请求或响应消息的应用程序必须 (MUST) 至少有条件地符合本规范。至少有条件地符合本规范的应用程序应该 (SHOULD) 在其消息中使用 "HTTP/1.1" 的 HTTP-Version,并且对于任何与 HTTP/1.0 不兼容的消息必须 (MUST) 这样做。有关何时发送特定 HTTP-Version 值的更多详细信息,请参见 RFC 2145 [36]。
应用程序的 HTTP 版本是该应用程序至少有条件地符合的最高 HTTP 版本。
代理和网关应用程序在转发与应用程序不同协议版本的消息时需要小心。由于协议版本指示发送方的协议能力,代理/网关禁止 (MUST NOT) 发送版本指示符大于其实际版本的消息。如果收到更高版本的请求,代理/网关必须 (MUST) 降级请求版本、响应错误或切换到隧道行为。
由于自 RFC 2068 [33] 发布以来发现了与 HTTP/1.0 代理的互操作性问题,缓存代理必须 (MUST)、网关可以 (MAY)、隧道禁止 (MUST NOT) 将请求升级到它们支持的最高版本。代理/网关对该请求的响应必须 (MUST) 与请求处于相同的主版本。
注意:在 HTTP 版本之间转换可能涉及修改所涉及版本要求或禁止的头字段。
3.2 Uniform Resource Identifiers (统一资源标识符)
URI 有许多名称:WWW 地址、通用文档标识符 (Universal Document Identifiers)、通用资源标识符 (Universal Resource Identifiers) [3],最后是统一资源定位符 (Uniform Resource Locators, URL) [4] 和名称 (Names, URN) [20] 的组合。就 HTTP 而言,统一资源标识符 (Uniform Resource Identifiers) 只是格式化的字符串,通过名称、位置或任何其他特征来标识资源。
3.2.1 General Syntax (通用语法)
HTTP 中的 URI 可以以绝对形式表示或相对于某个已知的基本 URI [11],具体取决于其使用的上下文。这两种形式的区别在于绝对 URI 始终以方案名称后跟冒号开头。有关 URL 语法和语义的权威信息,请参见"统一资源标识符 (URI):通用语法和语义",RFC 2396 [42](它取代了 RFC 1738 [4] 和 RFC 1808 [11])。本规范采用该规范中的 "URI-reference"、"absoluteURI"、"relativeURI"、"port"、"host"、"abs_path"、"rel_path" 和 "authority" 的定义。
HTTP 协议没有对 URI 的长度施加任何先验限制。服务器必须 (MUST) 能够处理它们所服务的任何资源的 URI,并且如果它们提供可能生成此类 URI 的基于 GET 的表单,则应该 (SHOULD) 能够处理无限长度的 URI。如果 URI 长于服务器可以处理的长度,服务器应该 (SHOULD) 返回 414(Request-URI Too Long)状态(参见第 10.4.15 节)。
注意:服务器应该谨慎依赖超过 255 字节的 URI 长度,因为某些较旧的客户端或代理实现可能无法正确支持这些长度。
3.2.2 http URL
"http" 方案用于通过 HTTP 协议定位网络资源。本节定义了 http URL 的特定于方案的语法和语义。
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
如果端口为空或未给出,则假定为端口 80。语义是所标识的资源位于该主机的该端口上侦听 TCP 连接的服务器上,资源的 Request-URI 是 abs_path(第 5.1.2 节)。应该 (SHOULD) 尽可能避免在 URL 中使用 IP 地址(参见 RFC 1900 [24])。如果 URL 中不存在 abs_path,则在用作资源的 Request-URI 时必须 (MUST) 将其指定为 "/"(第 5.1.2 节)。如果代理接收到的主机名不是完全限定的域名,它可以 (MAY) 将其域添加到它接收到的主机名。如果代理接收到完全限定的域名,代理禁止 (MUST NOT) 更改主机名。
3.2.3 URI Comparison (URI比较)
在比较两个 URI 以确定它们是否匹配时,客户端应该 (SHOULD) 对整个 URI 使用区分大小写的逐八位字节比较,但有以下例外:
- 空端口或未给出的端口等同于该 URI 引用的默认端口;
- 主机名的比较必须 (MUST) 不区分大小写;
- 方案名称的比较必须 (MUST) 不区分大小写;
- 空的 abs_path 等同于 "/" 的 abs_path。
"reserved" 和 "unsafe" 集合中的字符以外的字符(参见 RFC 2396 [42])等同于其 "%HEX HEX" 编码。
例如,以下三个 URI 是等效的:
http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html
3.3 Date/Time Formats (日期/时间格式)
3.3.1 Full Date (完整日期)
HTTP 应用程序历史上允许三种不同的日期/时间戳表示格式:
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
第一种格式作为互联网标准是首选的,并且代表 RFC 1123 [8](RFC 822 [9] 的更新)定义的固定长度子集。第二种格式很常用,但基于过时的 RFC 850 [12] 日期格式,并且缺少四位数的年份。解析日期值的 HTTP/1.1 客户端和服务器必须 (MUST) 接受所有三种格式(为了与 HTTP/1.0 兼容),但它们在头字段中表示 HTTP-date 值时必须 (MUST) 仅生成 RFC 1123 格式。有关更多信息,请参见第 19.3 节。
注意:鼓励日期值的接收方在接受可能由非 HTTP 应用程序发送的日期值时保持健壮性,这种情况有时会在通过代理/网关检索或发布消息到 SMTP 或 NNTP 时发生。
所有 HTTP 日期/时间戳必须 (MUST) 以格林威治标准时间 (Greenwich Mean Time, GMT) 表示,没有例外。就 HTTP 而言,GMT 完全等于 UTC(协调世界时)。这在前两种格式中通过将 "GMT" 作为时区的三字母缩写来指示,并且在读取 asctime 格式时必须 (MUST) 假定。HTTP-date 区分大小写,并且禁止 (MUST NOT) 包含语法中明确包含为 SP 的内容之外的额外 LWS。
HTTP-date = rfc1123-date | rfc850-date | asctime-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
rfc850-date = weekday "," SP date2 SP time SP "GMT"
asctime-date = wkday SP date3 SP time SP 4DIGIT
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
date2 = 2DIGIT "-" month "-" 2DIGIT
; day-month-year (e.g., 02-Jun-82)
date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
; month day (e.g., Jun 2)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" | "Tue" | "Wed"
| "Thu" | "Fri" | "Sat" | "Sun"
weekday = "Monday" | "Tuesday" | "Wednesday"
| "Thursday" | "Friday" | "Saturday" | "Sunday"
month = "Jan" | "Feb" | "Mar" | "Apr"
| "May" | "Jun" | "Jul" | "Aug"
| "Sep" | "Oct" | "Nov" | "Dec"
注意:日期/时间戳格式的 HTTP 要求仅适用于它们在协议流中的使用。客户端和服务器不需要为用户呈现、请求记录等使用这些格式。
3.3.2 Delta Seconds (增量秒数)
一些 HTTP 头字段允许将时间值指定为整数秒数,以十进制表示,在接收到消息的时间之后。
delta-seconds = 1*DIGIT
3.4 Character Sets (字符集)
HTTP 使用与 MIME 中描述的术语 "字符集" (character set) 相同的定义:
本文档中使用术语 "字符集" 来指代与一个或多个表一起使用以将八位字节序列转换为字符序列的方法。请注意,不需要在另一个方向上进行无条件转换,因为并非所有字符都可能在给定的字符集中可用,并且字符集可以提供多个八位字节序列来表示特定字符。此定义旨在允许各种字符编码,从简单的单表映射(如 US-ASCII)到复杂的表切换方法(如使用 ISO-2022 技术的方法)。但是,与 MIME 字符集名称关联的定义必须 (MUST) 完全指定要从八位字节到字符执行的映射。特别是,不允许使用外部配置文件信息来确定确切的映射。
注意:术语 "字符集" (character set) 的这种使用更常被称为 "字符编码" (character encoding)。但是,由于 HTTP 和 MIME 共享相同的注册表,术语也必须共享,这一点很重要。
HTTP 字符集由不区分大小写的标记 (tokens) 标识。完整的标记集由 IANA 字符集注册表 [19] 定义。
charset = token
虽然 HTTP 允许使用任意标记作为字符集值,但在 IANA 字符集注册表 [19] 中具有预定义值的任何标记必须 (MUST) 表示该注册表定义的字符集。应用程序应该 (SHOULD) 将其字符集的使用限制为 IANA 注册表定义的字符集。
实现者应该了解 IETF 字符集要求 [38] [41]。
3.4.1 Missing Charset (缺少字符集)
一些 HTTP/1.0 软件错误地将没有 charset 参数的 Content-Type 头解释为 "接收方应该猜测"。希望克服此行为的发送方可以 (MAY) 在字符集为 ISO-8859-1 时包含 charset 参数,并且应该 (SHOULD) 在已知不会混淆接收方时这样做。
不幸的是,一些较旧的 HTTP/1.0 客户端没有正确处理显式 charset 参数。HTTP/1.1 接收方必须 (MUST) 尊重发送方提供的 charset 标签;那些有 "猜测" 字符集规定的用户代理必须 (MUST) 使用来自内容类型字段的字符集,而不是接收方推断的字符集,即使发送方是 HTTP/1.0 客户端也是如此。
3.5 Content Codings (内容编码)
内容编码值指示已经或可以应用于实体的编码转换。内容编码主要用于允许在不丢失其底层媒体类型的标识和不丢失信息的情况下压缩文档。实体通常仅在其底层表示形式被编码用于传输时才以编码形式存储。
content-coding = token
所有内容编码值都不区分大小写。HTTP/1.1 在 Accept-Encoding 和 Content-Encoding 头字段中使用内容编码值。尽管该值描述应用于实体主体的内容编码,但更重要的是它指示可以应用什么解码机制来获得 Content-Type 头字段引用的媒体类型。
互联网分配号码管理局 (IANA) 充当内容编码值标记的注册表。最初,该注册表包含以下标记:
gzip 一种使用 Lempel-Ziv 编码 (LZ77) 和 32 位 CRC 的编码格式,如 RFC 1952 [25] 所述。此编码格式由 UNIX gzip 程序产生。HTTP/1.1 实现者被告知,出于历史原因,一些接收方将 "x-gzip" 和 "gzip" 视为等效。
compress 使用 Lempel-Ziv-Welch (LZW) 算法生成的编码格式。此编码格式由常见的 UNIX 文件压缩程序 "compress" 产生。出于历史原因,接收方应将 "x-compress" 和 "compress" 视为等效。
deflate RFC 1950 [31] 和 RFC 1951 [29] 中描述的 "zlib" 格式与 "deflate" 压缩机制的组合。
identity 默认(标识)编码;使用此内容编码仅表示没有进行编码。此内容编码用于 Accept-Encoding 头字段中,不应该 (SHOULD NOT) 用于 Content-Encoding 头字段中。
新的内容编码标记应该在 Internet Assigned Numbers Authority (IANA) 注册。
3.6 Transfer Codings (传输编码)
传输编码值用于指示已经、可以或可能需要应用于实体主体的编码转换,以确保通过网络的 "安全传输"。这与内容编码不同,因为传输编码是消息的属性,而不是原始实体的属性。
transfer-coding = "chunked" | transfer-extension
transfer-extension = token *( ";" parameter )
参数采用属性/值对的形式。
parameter = attribute "=" value
attribute = token
value = token | quoted-string
所有传输编码值都不区分大小写。HTTP/1.1 在 TE 头字段(第 14.39 节)和 Transfer-Encoding 头字段(第 14.41 节)中使用传输编码值。
传输编码是 HTTP/1.1 的新特性。除非消息指示为 HTTP/1.1 或更高版本,否则发送方禁止 (MUST NOT) 将传输编码应用于消息主体。
3.6.1 Chunked Transfer Coding (分块传输编码)
分块编码将消息主体修改为将其作为一系列块传输,每个块都有自己的大小指示符,后跟包含实体头字段的可选尾部 (trailer)。这允许动态生成的内容与有关消息的必要完整性检查信息一起传输。
Chunked-Body = *chunk
last-chunk
trailer
CRLF
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
chunk-size 字段是十六进制数字字符串,指示块数据的大小。分块编码以大小为零的块结束,后跟尾部,尾部由空行终止。
尾部允许发送方在消息末尾包含额外的 HTTP 头字段。Trailer 头字段(第 14.40 节)可用于指示哪些头字段包含在尾部中。
不允许在尾部中包含消息头字段,除非明确允许,如第 7.1 节所述。
如果接收方可接受的传输编码包括分块传输编码,则服务器可以 (MAY) 使用分块传输编码。尾部的存在可以通过在消息中包含 Trailer 头字段来表示。
接收分块消息主体的应用程序必须 (MUST) 忽略它不理解的块扩展,除非相应的块扩展由 Trailer 头字段定义。
3.7 Media Types (媒体类型)
HTTP 在 Content-Type(第 14.17 节)和 Accept(第 14.1 节)头字段中使用 Internet 媒体类型 [17] 来提供关于数据类型的开放式、可扩展数据类型和类型协商。
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token
类型、子类型和参数属性名称不区分大小写。参数值可能区分大小写,也可能不区分大小写,具体取决于参数名称的语义。线性空白 (LWS) 禁止 (MUST NOT) 在类型和子类型之间使用,也禁止 (MUST NOT) 在属性和其值之间使用。用户代理应该 (SHOULD) 尊重媒体类型参数标识的字符集标签(第 3.4 节)。
媒体类型值的存在并不意味着在 HTTP 消息中必须存在实体主体。对于某些方法或一些响应代码的响应消息,可能包括 Content-Type 头字段,即使消息中不包括实体主体。此类响应消息以空行开始,该空行终止头字段而不是实体主体。
3.7.1 Canonicalization and Text Defaults (规范化和文本默认值)
互联网媒体类型注册为标准的 "text" 主类型,采用与 MIME 相同的规则。这意味着如果 "text" 主类型的媒体类型的 Content-Type 头字段中未包含 "charset" 参数,则接收方应该 (SHOULD) 将其视为字符集为 "ISO-8859-1"(参见第 3.4.1 节)。HTTP 中 "text" 字节流的数据以 "规范形式" (canonical form) 发送;也就是说,HTTP 没有对 CRLF 行结束序列进行任何翻译。
3.7.2 Multipart Types (多部分类型)
MIME 提供了许多多部分类型——将一个或多个实体封装在单个消息主体中。所有多部分类型共享一个通用语法,如 MIME [7] 的第 5.1 节所定义,并且必须 (MUST) 包括边界参数作为媒体类型值的一部分。消息主体本身是一个协议元素,因此必须 (MUST) 使用 CRLF 作为两个主体部分之间的行分隔符。不像在 MIME 中,HTTP 中多部分主体的结尾必须 (MUST) 带有结束边界分隔符。
在 HTTP 中,应该 (SHOULD) 遵循与 MIME 中相同的用于多部分类型的 Content-Location 头的语义;但是,在 HTTP 中,任何具有 Content-Location 头的主体部分被视为具有独立的标识,即使它与其包含消息的外部 Content-Location 匹配也是如此。
通常,HTTP 将多部分主体部分视为单独的资源,每个都有自己的 URI。这允许在一个消息中并行发送多个资源或顺序发送,以及支持 206(Partial Content)响应。
3.8 Product Tokens (产品标记)
产品标记用于允许通信应用程序通过软件名称和版本标识自己。大多数使用产品标记的字段还允许列出子产品,这些子产品构成了应用程序的重要部分,由空格分隔。按照惯例,产品按其在应用程序中的重要性递减顺序列出。
product = token ["/" product-version]
product-version = token
示例:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4
产品标记应该 (SHOULD) 简短且无关紧要。它们不应该 (MUST NOT) 用于广告或其他非必要信息。尽管任何标记字符都可以出现在产品版本中,但该标记应该 (SHOULD) 仅用于产品的版本(即连续的版本应该仅在产品版本标记的值上有所不同)。
3.9 Quality Values (质量值)
HTTP 内容协商(第 12 节)使用短 "浮点" 数字来指示各种可协商参数的相对重要性("权重")。权重被标准化为 0 到 1 之间的实数值,其中 0 是最小值,1 是最大值。HTTP/1.1 应用程序禁止 (MUST NOT) 生成超过三位小数的质量值。用户配置这些值应该类似地限制。
qvalue = ( "0" [ "." 0*3DIGIT ] )
| ( "1" [ "." 0*3("0") ] )
"质量值" 的概念适用于任何内容(参见第 14.1 节)、字符集(第 14.2 节)、内容编码(第 14.3 节)、语言(第 14.4 节)或传输编码(第 14.39 节)的选择。然而,为了简洁起见,本节中使用的术语 "quality value" 指的是与该质量值相关的任何一个这些特性。
3.10 Language Tags (语言标签)
语言标签标识一种自然语言,如英语或法语,由一个或多个部分组成:主语言标签和可能的一系列子标签:
language-tag = primary-tag *( "-" subtag )
primary-tag = 1*8ALPHA
subtag = 1*8ALPHA
空格不允许在标签内,所有标签不区分大小写。标签的命名空间由 IANA 管理。示例标签包括:
en, en-US, en-cockney, i-cherokee, x-pig-latin
其中任何两个字符的主标签是 ISO-639 语言缩写 [34],任何两个字符的第一个子标签是 ISO-3166 国家代码 [35]。(ISO 639 的最后一个离线版本本文档编写时是 [35],但人们应该预期该标准随着时间的推移会继续发展。)
3.11 Entity Tags (实体标签)
实体标签用于在来自同一请求资源的多个表示之间进行比较。实体标签由不透明的带引号字符串组成,可能带有弱指示符前缀(参见第 13.3.3 节)。
entity-tag = [ weak ] opaque-tag
weak = "W/"
opaque-tag = quoted-string
"强实体标签" (strong entity tag) 可以在任何时候使用实体标签,无论实体值如何更改。"弱实体标签" (weak entity tag) 仅用于当实体值的语义等价性而不是字节等价性足够时的弱比较。
弱实体标签只能用于弱比较。如果没有弱指示符前缀,实体标签就是强实体标签。
实体标签必须 (MUST) 对于来自特定资源的两个实体是唯一的,除非这些实体的语义是等效的。
3.12 Range Units (范围单位)
HTTP/1.1 允许客户端请求仅传输响应实体的一部分(范围)。HTTP/1.1 在 Range(第 14.35 节)、Content-Range(第 14.16 节)和 Accept-Ranges(第 14.5 节)头字段中使用范围单位。实体可以根据不同的结构单位分解为子范围。
range-unit = bytes-unit | other-range-unit
bytes-unit = "bytes"
other-range-unit = token
HTTP/1.1 中唯一的范围单位是 "bytes"。HTTP/1.1 实现可以 (MAY) 忽略它们不理解的范围单位的规范。
HTTP/1.1 已注册用于 "bytes" 范围单位。附录包括了一些其他范围单位的注册。