[RFC2616-HTTP/1.1 超文本传输协议](翻译)[Part 1]

原文:RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 (ietf.org)

(因本篇RFC较长,将其分为几篇文章进行翻译)

超文本传输​​协议——HTTP/1.1

超文本传输​​协议 (HTTP) 是分布式、协作、超媒体信息系统的应用层协议。它是一种通用的、无状态的协议,通过扩展其请求方法、错误代码和标头 [47],可用于超文本之外的许多任务,例如名称服务器和分布式对象管理系统。 HTTP 的一个特性是数据表示的类型化和协商,允许独立于正在传输的数据构建系统。

自 1990 年以来,万维网全球信息倡议一直在使用 HTTP。该规范定义了称为“HTTP/1.1”的协议,是对 RFC 2068 [33] 的更新。

目录

   1 简介

   1.1 目的

   1.2 要求

   1.3 术语

   1.4 整体运作

   2 符号约定和通用语法

   2.1 增强 BNF

   2.2 基本规则

   3 协议参数

   3.1 HTTP 版本

   3.2 统一资源标识符

   3.2.1 一般语法

   3.2.2 http网址

   3.2.3 URI比较

   3.3 日期/时间格式

   3.3.1 完整日期

   3.3.2 增量秒

   3.4 字符集

   3.4.1 缺少字符集

   3.5 内容编码

   3.6 传输编码

   3.6.1 分块传输编码

   3.7 媒体类型

   3.7.1 规范化和文本默认值

   3.7.2 多部分类型

   3.8 产品代币

   3.9 质量价值观

   3.10 语言标签

   3.11 实体标签

   3.12 范围单位

   4 HTTP 消息

   4.1 消息类型

   4.2 消息头

   4.3 消息体

   4.4 消息长度

   4.5 通用头域

   5 请求

   5.1 请求行

   5.1.1 方法

   5.1.2 请求-URI

   5.2 请求标识的资源

   5.3 请求头域

   6 回应

   6.1 状态行

   6.1.1 状态码和原因短语

   6.2 响应头域

   7 实体

   7.1 实体头字段

   7.2 实体

   7.2.1 类型

   7.2.2 实体长度

   8. 连接

   8.1 持久连接

   8.1.1 目的

   8.1.2 整体运作

   8.1.3 代理服务器

   8.1.4 实际考虑

   8.2 消息传输要求

   8.2.1 持久连接和流控制

   8.2.2 监控错误状态消息的连接

   8.2.3 100(继续)状态的使用

   8.2.4 服务器过早关闭连接时的客户端行为

   9 方法定义

   9.1 安全和幂等方法

   9.1.1 安全方法

   9.1.2 幂等方法

   9.2 选项 Options

   9.3 Get

   9.4 Head

   9.5 Post

   9.6 Put

   9.7 Delete

   9.8 跟踪 Trace

   9.9 连接 Connect

   10 状态码定义

   10.1 信息 1xx

   10.1.1 100 继续

   10.1.2 101 交换协议

   10.2 成功2xx

   10.2.1 200 正常

   10.2.2 201 创建

   10.2.3 202 接受

   10.2.4 203 非权威信息

   10.2.5 204 无内容

   10.2.6 205 重置内容

   10.2.7 206 部分内容

   10.3 重定向 3xx

   10.3.1 300 多项选择

   10.3.2 301 永久移动

   10.3.3 302 找到

   10.3.4 303 见其他

   10.3.5 304 未修改

   10.3.6 305 使用代理

   10.3.7 306(未使用)

   10.3.8 307 临时重定向

   10.4 客户端错误 4xx

   10.4.1 400 错误请求

   10.4.2 401 未经授权

   10.4.3 402 需要付款 Payment Required

   10.4.4 403 禁止

   10.4.5 404 未找到

   10.4.6 405 方法不允许

   10.4.7 406 不可接受

   10.4.8 407 需要代理验证

   10.4.9 408 请求超时

   10.4.10 409 冲突

   10.4.11 410  Gone

   10.4.12 411 长度要求

   10.4.13 412 前置条件失败

   10.4.14 413 请求实体太大

   10.4.15 414 请求 URI 太长

   10.4.16 415 不支持的媒体类型

   10.4.17 416 请求的范围不满足

   10.4.18 417 预期失败

   10.5 服务器错误 5xx

   10.5.1 500 内部服务器错误

   10.5.2 501 未实施

   10.5.3 502 错误网关

   10.5.4 503 服务不可用

   10.5.5 504 网关超时

   10.5.6 505 HTTP 版本不支持

   11 访问认证

   12 内容协商

   12.1 服务器驱动的协商

   12.2 代理驱动的协商

   12.3 透明协商

   13 HTTP 中的缓存

   13.1.1 缓存正确性

   13.1.2 警告

   13.1.3 缓存控制机制

   13.1.4 显式用户代理警告

   13.1.5 规则和警告的例外情况

   13.1.6 客户端控制的行为

   13.2 到期模型

   13.2.1 服务器指定的过期时间

   13.2.2 启发式过期

   13.2.3 年龄计算 Age Calculations

   13.2.4 到期计算

   13.2.5 消除过期值的歧义

   13.2.6 消除多重响应的歧义

   13.3 验证模型

   13.3.1 最后修改日期

   13.3.2 实体标签缓存验证器

   13.3.3 弱验证器和强验证器

   13.3.4 何时使用实体标签和最后修改日期的规则

   13.3.5 非验证条件

   13.4 响应可缓存性

   13.5 从缓存构造响应

   13.5.1 端到端和逐跳报头

   13.5.2 不可修改的头文件

   13.5.3 组合标题

   13.5.4 组合字节范围

   13.6 缓存协商响应

   13.7 共享和非共享缓存

   13.8 错误或不完整的响应缓存行为

   13.9 GET 和 HEAD 的副作用

   13.10 更新或删除后失效

   13.11 强制直写

   13.12 缓存替换

   13.13 历史列表

   14 标题字段定义

   14.1 接受

   14.2 接受字符集

   14.3 接受编码

   14.4 接受语言

   14.5 接受范围

   14.6 年龄

   14.7 允许

   14.8 授权

   14.9 缓存控制

   14.9.1 什么是可缓存的

   14.9.2 缓存可以存储什么

   14.9.3 基本过期机制的修改

   14.9.4 缓存重新验证和重新加载控制

   14.9.5 无变换指令

   14.9.6 缓存控制扩展

   14.10 连接

   14.11 内容-编码

   14.12 内容-语言

   14.13 内容-长度

   14.14 内容-位置

   14.15 内容-MD5

   14.16 内容-范围

   14.17 内容-类型

   14.18 日期

   14.18.1 无时钟源服务器操作

   14.19 电子标签 Etag

   14.20 期待 Expect

   14.21 到期 Expires

  14.22 从 From

   14.23 主机

   14.24 如果匹配 If-Match

   14.25 If-Modified-Since

   14.26 If-None-Match

   14.27 如果范围If-Range

   14.28 If-Unmodified-Since

   14.29 最后修改 Last-Modified

   14.30 地点 Location

   14.31 最大转发 Max-Forwards

   14.32 杂注 Pragma

   14.33 代理认证 Proxy-Authenticate

   14.34 代理授权 Proxy-Authorization

   14.35 范围

   14.35.1 字节范围 Byte Ranges

   14.35.2 范围检索请求 Range Retrieval Requests

   14.36 推荐人 Referer

   14.37 重试后 Retry-After

   14.38 服务器

   14.39 TE

   14.40 预告片 Trailer

   14.41 传输编码 Transfer-Encoding

   14.42 升级 Upgrade

   14.43 用户代理 User-Agent

   14.44 变化 Vary

   14.45 过孔 Via

   14.46 警告 Warning

   14.47 WWW-认证 WWW-Authenticate

   15 安全注意事项

   15.1 个人信息

   15.1.1 滥用服务器日志信息

   15.1.2 敏感信息的传输

   15.1.3 在 URI 中编码敏感信息

   15.1.4 与接受标头相关的隐私问题

   15.2 基于文件名和路径名的攻击

   15.3 DNS 欺骗

   15.4 位置标头和欺骗

   15.5 内容处置问题 Content-Disposition Issues

   15.6 身份验证凭证和空闲客户端

   15.7 代理和缓存

   15.7.1 对代理的拒绝服务攻击

   16 致谢

   17 参考文献

   18 作者地址

   19 附录

   19.1 Internet 媒体类型 message/http 和 application/http

   19.2 互联网媒体类型 multipart/byteranges

   19.3 容差应用

   19.4 HTTP 实体和 RFC 2045 实体之间的区别

   19.4.1 MIME 版本

   19.4.2 转换为规范形式

   19.4.3 日期格式的转换

   19.4.4 Content-Encoding介绍

   19.4.5 无内容传输编码

   19.4.6 传输编码介绍

   19.4.7 MHTML 和行长限制

   19.5 附加功能

   19.5.1 内容处置

   19.6 与以前版本的兼容性

   19.6.1 从 HTTP/1.0 的变化

   19.6.2 与 HTTP/1.0 持久连接的兼容性

   19.6.3 对 RFC 2068 的更改

   20 指数

   21 完整的版权声明

1. 简介

1.1 目的

超文本传输​​协议 (HTTP) 是分布式、协作、超媒体信息系统的应用层协议。自 1990 年以来,万维网全球信息倡议一直在使用 HTTP。HTTP 的第一个版本,称为 HTTP/0.9,是一种用于通过 Internet 传输原始数据的简单协议。 RFC 1945 [6] 定义的 HTTP/1.0 通过允许消息采用类似 MIME 消息的格式来改进协议,其中包含有关传输数据的元信息和请求/响应语义上的修饰符。然而,HTTP/1.0 没有充分考虑分层代理、缓存、持久连接的需求或虚拟主机的影响。此外,自称为“HTTP/1.0”的未完全实现的应用程序激增,需要更改协议版本,以便两个通信应用程序确定彼此的真实能力。

该规范定义了称为“HTTP/1.1”的协议。该协议包含比 HTTP/1.0 更严格的要求,以确保其功能的可靠实现。

实用的信息系统需要比简单的检索更多的功能,包括搜索、前端更新和注释。 HTTP 允许一组开放的方法和标头指示请求的目的 [47]。它建立在统一资源标识符 (URI) [3] 提供的参考规则之上,作为位置 (URL) [4] 或名称 (URN) [20],用于指示要应用方法的资源。消息以类似于多用途 Internet 邮件扩展 (MIME) [7] 定义的 Internet 邮件 [9] 使用的格式传递。

HTTP 还用作用户代理和代理/网关与其他 Internet 系统之间通信的通用协议,包括 SMTP [16]、NNTP [13]、FTP [18]、Gopher [2] 和 WAIS [10]协议。通过这种方式,HTTP 允许对来自不同应用程序的可用资源进行基本的超媒体访问。

1.2 略

1.3 术语

本规范使用许多术语来指代 HTTP 通信的参与者和对象所扮演的角色。

联系connection

为通信目的在两个程序之间建立的传输层虚拟电路。

信息 message

HTTP 通信的基本单元,由与第 4 节中定义的语法匹配并通过连接传输的结构化八位字节序列组成。

请求 request

第 5 节中定义的 HTTP 请求消息。

回复response

第 6 节中定义的 HTTP 响应消息。

资源resource

可以由 URI 标识的网络数据对象或服务,如第 3.2 节中所定义。资源可能以多种表示形式(例如多种语言、数据格式、大小和分辨率)或以其他方式变化。

实体 entity

作为请求或响应的有效负载传输的信息。如第 7 节所述,实体由实体头字段形式的元信息和实体主体形式的内容组成。

表示 representation

如第 12 节所述,响应中包含的受内容协商的实体。可能存在与特定响应状态相关联的多个表示。

内容协商 content negotiation

服务请求时选择适当表示的机制,如第 12 节所述。可以协商任何响应中的实体表示(包括错误响应)。

变体 variant

在任何给定时刻,一个资源可能有一个或多个与其相关联的表示。这些表示中的每一个都称为“变体”。使用术语“变体”并不一定意味着资源受内容协商的影响。

客户 client

为发送请求而建立连接的程序。

用户代理 user agent

发起请求的客户端。这些通常是浏览器、编辑器、蜘蛛(网络遍历机器人)或其他终端用户工具。

服务器 server

一个应用程序,它接受连接以便通过发回响应来服务请求。任何给定的程序都可能既是客户端又是服务器;我们对这些术语的使用仅指程序为特定连接所执行的角色,而不是指程序的一般功能。同样,任何服务器都可以充当源服务器、代理、网关或隧道,根据每个请求的性质切换行为。

源服务器 origin server

给定资源驻留或将被创建的服务器。

代理 proxy

一种中间程序,它既充当服务器又充当客户端,以代表其他客户端发出请求。请求在内部得到服务,或者通过可能的翻译将它们传递给其他服务器。代理必须实现本规范的客户端和服务器要求。 “透明代理”是一种不会修改超出代理身份验证和识别所需的请求或响应的代理。 “非透明代理”是修改请求或响应以便为用户代理提供一些附加服务的代理,例如组注释服务、媒体类型转换、协议缩减或匿名过滤。除非明确说明透明或非透明行为,HTTP 代理要求适用于这两种类型的代理。

网关 gateway

充当其他服务器的中介的服务器。与代理不同,网关接收请求,就好像它是所请求资源的源服务器一样;请求客户端可能不知道它正在与网关通信。

隧道tunnel

充当两个连接之间的盲中继的中间程序。一旦激活,隧道就不会被认为是 HTTP 通信的一方,尽管隧道可能是由 HTTP 请求发起的。当中继连接的两端都关闭时,隧道将不复存在。

缓存 cache

程序的本地响应消息存储和控制其消息存储、检索和删除的子系统。缓存存储可缓存的响应,以减少未来等效请求的响应时间和网络带宽消耗。任何客户端或服务器都可能包含缓存,尽管缓存不能被充当隧道的服务器使用。

可缓存的 cacheable

如果允许缓存存储响应消息的副本以用于响应后续请求,则响应是可缓存的。确定 HTTP 响应的可缓存性的规则在第 13 节中定义。即使资源是可缓存的,缓存是否可以将缓存的副本用于特定请求也可能存在额外的限制。

第一手 first-hand

如果响应直接来自原始服务器且没有不必要的延迟,则响应是第一手的,可能通过一个或多个代理。如果刚刚与原始服务器直接检查了响应的有效性,则响应也是第一手的。

明确的过期时间 explicit expiration time

源服务器打算在没有进一步验证的情况下不再由缓存返回实体的时间。

启发式过期时间 heuristic expiration time

当没有明确的过期时间可用时,缓存分配的过期时间。

年龄 age

响应的年龄是自原始服务器发送或成功验证以来的时间。

保鲜期 freshness lifetime

响应生成与其到期时间之间的时间长度。

新鲜的 fresh

如果响应的年龄尚未超过其刷新的生命周期,则该响应是新的(fresh)。

陈旧 stale

如果响应的年龄已超过其刷新的生命周期,则响应是陈旧的。

语义透明 semantically transparent

当缓存的使用既不影响请求客户端也不影响源服务器时,缓存以“语义透明”的方式运行,只是为了提高性能。当缓存在语义上是透明的时,客户端会收到与它的请求由源服务器直接处理时收到的完全相同的响应(逐跳标头除外)。

验证器 validator

一个协议元素(例如,实体标签或 Last-Modified 时间),用于确定缓存条目是否是实体的等效副本。

上游/下游 (upstream/downstream)

上游和下游描述了消息的流向:所有消息都从上游流向下游。

入站/出站 (inbound/outbound)

入站和出站是指消息的请求和响应路径:“入站”表示“前往源服务器”,“出站”表示“前往用户代理”。

1.4 整体运作

HTTP 协议是一个请求/响应协议。客户端以请求方法、URI 和协议版本的形式向服务器发送请求,然后是类似于 MIME 的消息,其中包含请求修饰符、客户端信息和通过与服务器的连接可能的正文内容。服务器以状态行进行响应,包括消息的协议版本和成功或错误代码,然后是类似于 MIME 的消息,其中包含服务器信息、实体元信息和可能的实体主体内容。 HTTP 和 MIME 的关系在附录中描述。

大多数 HTTP 通信是由用户代理发起的,并且由一个请求组成,该请求将应用于某个源服务器上的资源。 在最简单的情况下,这可以通过用户代理 (UA) 和源服务器 (O) 之间的单个连接 (v) 来完成。

          request chain ------------------------>

       UA -------------------v------------------- O

          <----------------------- response chain

当请求/响应链中存在一个或多个中介时,会出现更复杂的情况。 存在三种常见的中介形式:代理、网关和隧道。 代理是一个转发代理,以绝对形式接收对 URI 的请求,重写全部或部分消息,并将重新格式化的请求转发到由 URI 标识的服务器。 网关是一个接收代理,充当其他一些服务器之上的一层,并在必要时将请求转换为底层服务器的协议。 隧道充当两个连接之间的中继点,而不会更改消息; 当通信需要通过中介(例如防火墙)时使用隧道,即使中介无法理解消息的内容。

          request chain -------------------------------------->
       UA -----v----- A -----v----- B -----v----- C -----v----- O
          <------------------------------------- response chain

上图显示了用户代理和源服务器之间的三个中介(A、B 和 C)。穿过整个链的请求或响应消息将通过四个单独的连接。这种区别很重要,因为某些 HTTP 通信选项可能仅适用于与最近的非隧道邻居的连接,仅适用于链的端点,或链上的所有连接。尽管该图是线性的,但每个参与者都可以参与多个同时进行的通信。例如,B 可能正在接收来自除 A 之外的许多客户端的请求,和/或将请求转发到除 C 之外的服务器,同时它正在处理 A 的请求。

任何不充当隧道的通信方都可以使用内部缓存来处理请求。缓存的效果是,如果链上的参与者之一具有适用于该请求的缓存响应,则请求/响应链会缩短。下面说明了如果 B 拥有来自 O(通过 C)的早期响应的缓存副本,该副本针对尚未被 UA 或 A 缓存的请求,则生成的链。

          request chain ---------->
       UA -----v----- A -----v----- B - - - - - - C - - - - - - O
          <--------- response chain

并非所有响应都可以有效地缓存,并且某些请求可能包含对缓存行为提出特殊要求的修饰符。缓存行为和可缓存响应的 HTTP 要求在第 13 节中定义。

事实上,目前有各种各样的架构和配置的缓存和代理正在万维网上进行试验或部署。这些系统包括用于节省跨洋带宽的代理缓存的国家层次结构、广播或多播缓存条目的系统、通过 CD-ROM 分发缓存数据子集的组织等。 HTTP 系统用于企业内部网中的高带宽链路,以及通过具有低功率无线电链路和间歇性连接的 PDA 进行访问。 HTTP/1.1 的目标是支持已经部署的各种配置,同时引入协议结构,以满足那些构建需要高可靠性的 Web 应用程序的人的需求,如果做不到这一点,至少需要可靠的故障指示。

HTTP 通信通常通过 TCP/IP 连接进行。默认端口是 TCP 80 [19],但也可以使用其他端口。这并不排除 HTTP 在 Internet 或其他网络上的任何其他协议之上实现。 HTTP 只假定可靠的传输;可以使用任何提供此类保证的协议; HTTP/1.1 请求和响应结构到相关协议的传输数据单元的映射超出了本规范的范围。

在 HTTP/1.0 中,大多数实现为每个请求/响应交换使用一个新连接。在 HTTP/1.1 中,一个连接可以用于一个或多个请求/响应交换,尽管连接可能由于各种原因而关闭(参见第 8.1 节)。

3. 协议参数

3.1 HTTP 版本

HTTP 使用“<major>.<minor>”编号方案来指示协议的版本。协议版本控制策略旨在允许发送者指示消息的格式及其理解进一步 HTTP 通信的能力,而不是通过该通信获得的特性。添加不影响通信行为或仅添加到可扩展字段值的消息组件的版本号不会更改。当对协议所做的更改添加了不会更改一般消息解析算法但可能会增加消息语义并暗示发送者的附加功能的功能时,<minor> 数字会增加。当协议中的消息格式发生变化时,<major> 数字会增加。有关更完整的解释,请参阅 RFC 2145 [36]。 HTTP 消息的版本由消息第一行中的 HTTP-Version 字段指示。

HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT

请注意,主要和次要数字必须被视为单独的整数,并且每个数字的增量都可以高于单个数字。因此,HTTP/2.4 的版本低于 HTTP/2.13,而 HTTP/2.13 又低于 HTTP/12.3。接收者必须忽略前导零,并且不得发送。

发送包含“HTTP/1.1”的 HTTP 版本的请求或响应消息的应用程序必须至少有条件地符合本规范。至少有条件地符合本规范的应用程序应该在其消息中使用“HTTP/1.1”的 HTTP 版本,并且必须对任何与 HTTP/1.0 不兼容的消息这样做。有关何时发送特定 HTTP-Version 值的更多详细信息,请参阅 RFC 2145 [36]。

应用程序的 HTTP 版本是应用程序至少有条件地兼容的最高 HTTP 版本。

代理和网关应用程序在转发与应用程序不同的协议版本的消息时需要小心。由于协议版本指示发送方的协议能力,代理/网关不得发送带有大于其实际版本的版本指示符的消息。如果收到更高版本的请求,代理/网关必须要么降级请求版本,要么响应错误,要么切换到隧道行为。

由于自 RFC 2068[33] 发布以来发现的 HTTP/1.0 代理的互操作性问题,缓存代理必须、网关可以,和隧道不得将请求升级到它们支持的最高版本。代理/网关对该请求的响应必须与请求的主要版本相同。

注意:HTTP 版本之间的转换可能涉及修改相关版本要求或禁止的标头字段。

3.2 统一资源标识符

URI 有许多名称:WWW 地址、通用文档标识符、通用资源标识符 [3],最后是统一资源定位符 (URL) [4] 和名称 (URN) [20] 的组合。就 HTTP 而言,统一资源标识符是简单的格式化字符串,通过名称、位置或任何其他特征来标识资源。

3.2.1 一般语法

HTTP 中的 URI 可以以绝对形式表示,也可以相对于某些已知的基本 URI [11] 表示,具体取决于它们的使用上下文。这两种形式的区别在于绝对 URI 总是以方案名称开头,后跟冒号。有关 URL 语法和语义的明确信息,请参阅“统一资源标识符 (URI):通用语法和语义”,RFC 2396 [42](取代 RFCs1738 [4] 和 RFC 1808 [11])。本规范采用了该规范中“URI-reference”、“absoluteURI”、“relativeURI”、“port”、“host”、“abs_path”、“rel_path”和“authority”的定义。

HTTP 协议对 URI 的长度没有任何先验限制。服务器必须能够处理它们所服务的任何资源的 URI,并且如果它们提供可以生成此类 URI 的基于 GET 的表单,则应该能够处理无限长度的 URI。如果 URI 比服务器可以处理的长(参见第 10.4.15 节),服务器应该返回 414(Request-URI Too Long)状态。

注意:服务器应该谨慎依赖 URI 长度超过 255 字节,因为一些较旧的客户端或代理实现可能无法正确支持这些长度。

3.2.2 http网址

“http”方案用于通过 HTTP 协议定位网络资源。本节定义了 http URL 的特定于方案的语法和语义。

http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]

如果端口为空或未给出,则假定端口为 80。语义是识别的资源位于服务器上侦听该主机的该端口上的 TCP 连接,并且资源的 Request-URI 是 abs_path (第 5.1.2 节)。应尽可能避免在 URL 中使用 IP 地址(参见 RFC 1900 [24])。如果 URL 中不存在 abs_path,则在用作资源的 Request-URI 时必须将其指定为“/”(第 5.1.2 节)。如果代理收到一个不是完全限定域名的主机名 (FQDN),它可以将其域添加到它收到的主机名中。如果代理收到完全限定的域名 (FQDN),则代理不得更改主机名。

3.2.3 URI比较

在比较两个 URI 以确定它们是否匹配时,客户端应该使用区分大小写的字节对整个 URI 进行逐个字节比较,但以下情况除外:

        - 空端口或未指定端口等效于该 URI 引用的默认端口;

        - 主机名的比较必须不区分大小写;

        - 方案名称的比较必须不区分大小写;

        - 空的 abs_path 等效于 "/" 的 abs_path。

“保留”和“不安全”集合(参见 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 日期/时间格式

3.3.1 完整日期

HTTP 应用程序历来允许三种不同的日期/时间戳表示格式:

      格林威治标准时间 1994 年 11 月 6 日星期日 08:49:37; RFC 822,由 RFC 1123 更新

      格林威治标准时间 94 年 11 月 6 日星期日 08:49:37; RFC 850,已被 RFC 1036 淘汰

      1994 年 11 月 6 日星期日 08:49:37 ; ANSI C 的 asctime() 格式

第一种格式是首选的 Internet 标准,它代表 RFC 1123 [8](对 RFC 822 [9] 的更新)定义的固定长度子集。第二种格式是常用的,但基于过时的 RFC 850 [12] 日期格式并且缺少四位数的年份。解析日期值的 HTTP/1.1 客户端和服务器必须接受所有三种格式(为了与 HTTP/1.0 兼容),尽管它们必须只生成 RFC 1123 格式来表示标头字段中的 HTTP 日期值。有关详细信息,请参阅第 19.3 节。

注意:鼓励日期值的接收者在接受可能由非 HTTP 应用程序发送的日期值时保持稳健,有时通过代理/网关检索或发布消息到 SMTP 或 NNTP 时就是这种情况。

所有 HTTP 日期/时间戳必须以格林威治标准时间 (GMT) 表示,无一例外。就 HTTP 而言,GMT 与 UTC(协调世界时)完全相同。这在前两种格式中通过包含“GMT”作为时区的三个字母缩写来表示,并且在读取 asctime 格式时必须假设。 HTTP-date 区分大小写,除了语法中特别包含的 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 增量秒

某些 HTTP 标头字段允许将时间值指定为接收消息后的整数秒数,以十进制表示。

       增量秒 = 1*DIGIT

3.4 字符集

HTTP 使用与 MIME 描述的术语“字符集”相同的定义:

本文档中使用的术语“字符集”是指与一个或多个表一起使用以将八位字节序列转换为字符序列的方法。请注意,不需要在另一个方向上进行无条件转换,因为在给定字符集中并非所有字符都可用,并且字符集可以提供多个八位位组序列来表示特定字符​​。此定义旨在允许各种字符编码,从简单的单表映射(如 US-ASCII)到复杂的表切换方法(如使用 ISO-2022 技术的方法)。但是,与 MIME 字符集名称相关的定义必须完全指定要执行的从八位字节到字符的映射。特别是,不允许使用外部分析信息来确定准确的映射。

注意:术语“字符集”的这种使用通常被称为“字符编码”。但是,由于 HTTP 和 MIME 共享相同的注册表,因此术语也必须共享,这一点很重要。

HTTP 字符集由不区分大小写的标记标识。完整的令牌集由 IANA 字符集注册表 [19] 定义。

字符集 = 令牌

尽管 HTTP 允许将任意令牌用作字符集值,但在 IANA 字符集注册表 [19] 中具有预定义值的任何令牌都必须表示由该注册表定义的字符集。应用程序应将其对字符集的使用限制为 IANA 注册机构定义的字符集。

实施者应该了解 IETF 字符集要求 [38] [41]。

3.4.1 缺少字符集

一些 HTTP/1.0 软件错误地将没有字符集参数的 Content-Type 标头解释为“收件人应该猜测”。即使字符集是 ISO-8859-1,希望阻止这种行为的发件人也可以包含一个字符集参数,并且当知道它不会混淆收件人时应该这样做。

不幸的是,一些较旧的 HTTP/1.0 客户端无法正确处理显式字符集参数。 HTTP/1.1 接收者必须尊重发送者提供的字符集标签;并且那些有“猜测”字符集的用户代理在最初显示文档时,如果他们支持该字符集而不是接收者的偏好,则必须使用内容类型字段中的字符集。请参阅第 3.7.1 节。

3.5 内容编码

内容编码值表示已经或可以应用于实体的编码转换。内容编码主要用于允许对文档进行压缩或以其他方式进行有用的转换,而不会丢失其底层媒体类型的身份,也不会丢失信息。通常,实体以编码形式存储,直接传输,并且仅由接收者解码。

       content-coding   = token

所有内容编码值都不区分大小写。 HTTP/1.1 在 Accept-Encoding(第 14.3 节)和 Content-Encoding(第 14.11 节)标头字段中使用内容编码值。尽管该值描述了内容编码,但更重要的是它指示了删除编码需要什么解码机制。

互联网号码分配机构 (IANA) 充当内容编码值令牌 (content-coding value tokens) 的注册机构。最初,注册表包含以下令牌(tokens):

gzip

由文件压缩程序“gzip”(GNU zip)产生的一种编码格式,如 RFC 1952 [25] 中所述。此格式是具有 32 位 CRC 的 Lempel-Ziv 编码 (LZ77)。

压缩

常见的 UNIX 文件压缩程序“compress”产生的编码格式。这种格式是自适应 Lempel-Ziv-Welch 编码 (LZW)。

使用程序名称来识别编码格式是不可取的,并且不鼓励用于未来的编码。它们在这里的使用是历史实践的代表,而不是好的设计。为了与以前的 HTTP 实现兼容,应用程序应该考虑 "x-gzip" 和 "x-compress" 分别等同于 "gzip" 和 "compress"。

Deflate

RFC 1950 [31] 中定义的“zlib”格式与 RFC 1951 [29] 中描述的“deflate”压缩机制相结合。

Identity

默认(身份)编码;不使用任何转换。此内容编码仅在 Accept-Encoding 标头中使用,不应在 Content-Encoding 标头中使用。

应该注册新的内容编码值令牌;为了允许客户端和服务器之间的互操作性,实现新值所需的内容编码算法的规范应该是公开的并且足以独立实现,并且符合本节中定义的内容编码的目的。

3.6 传输编码

传输编码值用于指示已经、可以或可能需要应用于实体主体的编码转换,以确保通过网络的“安全传输”。

这与内容编码的不同之处在于,传输编码是消息的属性,而不是原始实体的属性。

        transfer-coding         = "chunked" | transfer-extension
       transfer-extension      = token *( ";" parameter )
   Parameters are in  the form of attribute/value pairs.
       parameter               = attribute "=" value
       attribute               = token
       value                   = token | quoted-string

所有传输编码值都不区分大小写。 HTTP/1.1 在 TE 标头字段(第 14.39 节)和 Transfer-Encoding 标头字段(第 14.41 节)中使用传输编码值。

每当将传输编码应用于消息体时,传输编码集必须包括“分块”,除非通过关闭连接来终止消息。当使用“分块”传输编码时,它必须是应用于消息体的最后一个传输编码。 “分块”传输编码不得多次应用于消息正文。这些规则允许接收者确定消息的传输长度(第 4.4 节)。

传输编码类似于 MIME [7] 中的 Content-Transfer-Encoding 值,旨在通过 7 位传输服务实现二进制数据的安全传输。然而,安全传输对 8bit-clean 传输协议有不同的关注点。在 HTTP 中,消息体的唯一不安全特征是难以确定确切的正文长度(第 7.2.2 节),或者希望通过共享传输加密数据。互联网号码分配机构 (IANA) 充当传输编码价值令牌的注册机构。最初,注册表包含以下标记:“chunked”(第 3.6.1 节)、“identity”(第 3.6.2 节)、“gzip”(第 3.5 节)、“compress”(第 3.5 节)和“deflate”(第 3.5 节)。

新的传输编码值令牌应该以与新的内容编码值令牌相同的方式注册(第 3.5 节)。

接收到带有它不理解的传输编码的实体主体的服务器应该返回 501(未实现),并关闭连接。服务器不得向 HTTP/1.0 客户端发送传输编码。

3.6.1 分块传输编码

分块编码修改消息的主体,以便将其作为一系列块传输,每个块都有自己的大小指示符,后跟一个包含实体头字段的可选尾部。这允许动态生成的内容与接收者验证其已收到完整消息所需的信息一起传输。

        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 节)。

除非以下至少一项为真,否则在响应中使用分块传输编码的服务器不得将尾部用于任何头字段:

   a) 请求包含一个 TE 标头字段,该字段指示“trailers”在响应的传输编码中是可接受的,如第 14.39 节所述;或者,

   b) 服务器是响应的源服务器,尾部字段完全由可选的元数据组成,接收者可以使用消息(以源服务器可接受的方式)而不接收此元数据。换句话说,源服务器愿意接受尾部字段可能在通往客户端的路径上被静默丢弃的可能性。

当消息被 HTTP/1.1(或更高版本)代理接收并转发给 HTTP/1.0 收件人时,此要求可防止互操作性失败。它避免了遵守协议可能需要代理上的无限缓冲区的情况。

附录 19.4.6 中介绍了解码块体的示例过程。

所有 HTTP/1.1 应用程序必须能够接收和解码“分块”传输编码,并且必须忽略他们不理解的块扩展扩展。

3.7 媒体类型

HTTP 在 Content-Type(第 14.17 节)和 Accept(第 14.1 节)标头字段中使用 Internet 媒体类型 [17],以提供开放和可扩展的数据类型和类型协商。

       media-type     = type "/" subtype *( ";" parameter )
       type           = token
       subtype        = token

参数可以以属性/值对的形式跟随类型/子类型(如第 3.6 节中所定义)。

类型、子类型和参数属性名称不区分大小写。参数值可能区分大小写,也可能不区分大小写,具体取决于参数名称的语义。线性空白(LWS)不得在类型和子类型之间使用,也不得在属性与其值之间使用。参数的存在与否可能对媒体类型的处理很重要,这取决于它在媒体类型注册表中的定义。

请注意,一些较旧的 HTTP 应用程序无法识别媒体类型参数。当向旧的 HTTP 应用程序发送数据时,实现应该只在该类型/子类型定义需要时使用媒体类型参数。

媒体类型值在 Internet 号码分配机构 (IANA [19]) 注册。 RFC 1590 [17] 中概述了媒体类型注册过程。不鼓励使用未注册的媒体类型。

3.7.1 规范化和文本默认值

Internet 媒体类型以规范形式注册。通过 HTTP 消息传输的实体主体必须在传输之前以适当的规范形式表示,“文本”类型除外,如下一段中定义。

当采用规范形式时,“文本”类型的媒体子类型使用 CRLF 作为文本换行符。 HTTP 放宽了这一要求,并允许传输具有纯 CR 或 LF 的文本媒体,当它对整个实体主体一致完成时,它代表一个换行符。 HTTP 应用程序必须接受 CRLF、裸 CR 和裸 LF 作为通过 HTTP 接收的文本媒体中的换行符的代表。此外,如果文本以不分别对 CR 和 LF 使用八位字节 13 和 10 的字符集表示,就像某些多字节字符集的情况一样,HTTP 允许使用由该字符集定义的任何八位字节序列字符集来表示相当于换行符的 CR 和 LF。这种关于换行的灵活性仅适用于实体主体中的文本媒体;在任何 HTTP 控制结构(例如标头字段和多部分边界)中,不得用裸 CR 或 LF 替换 CRLF。

如果实体主体使用内容编码进行编码,则底层数据必须采用上面定义的格式,然后再进行编码。

“charset”参数与某些媒体类型一起使用来定义数据的字符集(第 3.4 节)。当发送者没有提供明确的字符集参数时,“文本”类型的媒体子类型被定义为在通过 HTTP 接收时具有“ISO-8859-1”的默认字符集值。除“ISO-8859-1”或其子集以外的字符集中的数据必须用适当的字符集值标记。有关兼容性问题,请参阅第 3.4.1 节。

3.7.2 多部分类型 Multipart Types

MIME 提供了许多“多部分”类型——将一个或多个实体封装在单个消息体中。如 RFC 2046 [40] 的 5.1.1 节中所定义,所有多部分类型共享一个通用语法,并且必须包含边界参数作为媒体类型值的一部分。消息体本身就是一个协议元素,因此必须只使用 CRLF 来表示正文部分之间的换行符。与 RFC 2046 不同,任何多部分消息的结尾必须为空; HTTP 应用程序不得传输结语(即使原始多部分包含结语)。存在这些限制是为了保持多部分消息体的自定界性质,其中消息体的“结束”由结束多部分边界指示。

一般来说,HTTP 对待多部分消息体与任何其他媒体类型没有区别:严格作为有效负载。一个例外是“multipart/byteranges”类型(附录 19.2),当它出现在 206(部分内容)响应中时,它将由 13.5.4 和 14.16 节中描述的一些 HTTP 缓存机制解释。在所有其他情况下,HTTP 用户代理应该遵循与 MIME 用户代理在收到多部分类型时相同或相似的行为。多部分消息正文的每个正文部分中的 MIME 标头字段对 HTTP 没有任何意义,超出其 MIME 语义定义的意义。

一般来说,HTTP 用户代理应该遵循与 MIME 用户代理在收到多部分类型时相同或相似的行为。如果应用程序接收到无法识别的多部分子类型,应用程序必须将其视为等同于“multipart/mixed”。

注意:如 RFC 1867 [15] 中所述,“multipart/form-data”类型已被专门定义为携带适合通过 POST 请求方法处理的表单数据。

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

产品令牌应该简短明了。它们不得用于广告或其他非必要信息。尽管任何标记字符都可能出现在产品版本中,但此标记应仅用于版本标识符(即,同一产品的连续版本应仅在产品值的产品版本部分有所不同)。

3.9 质量值 (Quality Values)

HTTP 内容协商(第 12 节)使用短的“浮点”数字来表示各种可协商参数的相对重要性(“权重”)。权重被归一化为 0 到 1 范围内的实数,其中 0 是最小值,1 是最大值。如果一个参数的质量值为 0,那么这个参数的内容对于客户端来说是“不可接受的”。 HTTP/1.1 应用程序生成的小数点后不得超过三位。这些值的用户配置也应该以这种方式进行限制。

       qvalue = ( "0" [ "." 0*3DIGIT ] )

                      | ( "1" [ "." 0*3("0") ] )

“质量值”是用词不当,因为这些值仅代表所需质量的相对下降。

3.10 语言标签 (Language Tags)

语言标签标识由人类说出、书写或以其他方式传达的自然语言,用于与其他人进行信息交流。计算机语言被明确排除。 HTTP 在 Accept-Language 和 Content-Language 字段中使用语言标签。

HTTP 语言标签的语法和注册与 RFC 1766 [1] 定义的相同。总之,一个语言标签由一个或多个部分组成:一个主要语言标签和一系列可能为空的子标签:

        语言标签=主标签*(“-”子标签)

        主标签 = 1*8ALPHA

        子标签 = 1*8ALPHA

标签中不允许有空格,并且所有标签都不区分大小写。语言标签的名称空间由 IANA 管理。示例标签包括:

       en, en-US, en-cockney, i-cherokee, x-pig-latin

其中任何两个字母的主标签是 ISO-639 语言缩写,任何两个字母的初始子标签都是 ISO-3166 国家代码。 (上面的最后三个标签不是注册标签;除了最后一个之外都是未来可能注册的标签示例。)

3.11 实体标签

实体标签用于比较来自同一请求资源的两个或多个实体。 HTTP/1.1 在 ETag(第 14.19 节)、If-Match(第 14.24 节)、If-None-Match(第 14.26 节)和 If-Range(第 14.27 节)标头字段中使用实体标签。13.3.3 节中定义了如何将它们用作缓存验证器并进行比较。实体标签由不透明的引号字符串组成,可能以弱点指示符为前缀。

      实体标签 = [ 弱 ] 不透明标签

      弱 = “W/”

      不透明标签 = 引用字符串

(     entity-tag = [ weak ] opaque-tag
      weak       = "W/"
      opaque-tag = quoted-string)

一个“强实体标签”可以由一个资源的两个实体共享,前提是它们在八位字节相等的情况下是等价的。

由“W/”前缀表示的“弱实体标签”可以由资源的两个实体共享,前提是这些实体是等效的并且可以在语义上没有显着变化的情况下相互替换。弱实体标签只能用于弱比较。

一个实体标签在与特定资源相关的所有实体的所有版本中必须是唯一的。给定的实体标签值可以用于通过不同 URI 上的请求获得的实体。将相同的实体标签值与通过不同 URI 上的请求获得的实体结合使用并不意味着这些实体的等价性。

3.12 范围单位

HTTP/1.1 允许客户端请求仅响应实体的一部分(范围)包含在响应中。 HTTP/1.1 在 Range(第 14.35 节)和 Content-Range(第 14.16 节)标头字段中使用范围单位。一个实体可以根据各种结构单元分解为子范围。

      范围单位 = 字节单位 |其他范围单位

      字节单位=“字节”

      其他范围单位 = 令牌

HTTP/1.1 定义的唯一范围单位是“字节”。 HTTP/1.1 实现可以忽略使用其他单位指定的范围 。HTTP/1.1 被设计为允许不依赖于范围知识的应用程序的实现。

4 HTTP 消息

4.1 消息类型

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

       HTTP 消息 = 请求 |回复     ; HTTP/1.1 消息

请求(第 5 节)和响应(第 6 节)消息使用 RFC 822 [9] 的通用消息格式来传输实体(消息的有效负载)。两种类型的消息都包含一个起始行、零个或多个标题字段(也称为“标题”)、一个指示标题字段结束的空行(即,在 CRLF 之前没有任何内容的行),可能还有一个消息正文。

        通用消息 = 起始行

                          *(消息头 CRLF)

                          CRLF

                          [ 邮件正文 ]

        start-line = 请求行 |状态行

出于健壮性的考虑,服务器应该忽略任何接收到的空行,这些空行是预期的请求行。换句话说,如果服务器在消息的开头读取协议流并首先收到 CRLF,它应该忽略 CRLF。

某些有缺陷的 HTTP/1.0 客户端实现会在 POST 请求后生成额外的 CRLF。为了重申 BNF 明确禁止的内容,HTTP/1.1 客户端不得在请求之前或之后使用额外的 CRLF。

4.2 消息头

HTTP 标头字段,包括 general-header(第 4.5 节)、request-header(第 5.3 节)、response-header(第 6.2 节)和 entity-header(第 7.1 节)字段,遵循与第 7.1 节中给出的相同的通用格式RFC 822 [9] 的 3.1。每个标头字段由一个名称后跟一个冒号(“:”)和字段值(field value) 组成。字段名称(Field names)不区分大小写。字段值可以在任意数量的 LWS 之前,但最好使用单个 SP。通过在每个额外行之前至少使用一个 SP 或 HT,可以将标题字段扩展到多行。在生成 HTTP 结构时,应用程序应该遵循已知或指示的“通用形式”,因为可能存在一些无法接受超出通用形式的任何实现的实现。

       消息头 = 字段名“:” [字段值]

       字段名 = 令牌

       字段值 = *( 字段内容 | LWS )

       field-content = <组成字段值的八位字节,并由 *TEXT 或令牌、分隔符和引号字符串组合组成 >

字段内容不包括任何前导或尾随 LWS:

出现在字段值的第一个非空白字符之前或字段值的最后一个非空白字符之后的线性空白。可以在不更改字段值语义的情况下删除此类前导或尾随 LWS。在解释字段值或向下游转发消息之前,在字段内容之间发生的任何 LWS 都可以用单个 SP 替换。

接收具有不同字段名称的头字段的顺序并不重要。但是,首先发送通用头字段,然后是请求头或响应头字段,并以实体头字段结束是“好习惯”。

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

4.3 消息体

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

       消息体 = 实体体

                    | <根据传输编码编码的实体主体>

Transfer-Encoding 必须用于指示应用程序应用的任何传输编码,以确保消息的安全和正确传输。 Transfer-Encoding 是消息的属性,而不是实体的属性,因此可以由请求/响应链上的任何应用程序添加或删除。 (但是,第 3.6 节对何时可以使用某些传输编码进行了限制。)

消息中何时允许消息正文的规则因请求和响应而异。

请求中消息体的存在是通过在请求的消息头中包含 Content-Length 或 Transfer-Encoding 头字段来表示的。如果请求方法的规范(第 5.1.1 节)不允许在请求中发送实体主体,则消息主体不得包含在请求中。服务器应该在任何请求上读取并转发消息体;如果请求方法不包括为实体主体定义的语义,则在处理请求时应该忽略消息主体。

对于响应消息,消息中是否包含消息正文取决于请求方法和响应状态代码(第 6.1.1 节)。对 HEAD 请求方法的所有响应都不能包含消息体,即使实体头字段的存在可能会让人们相信它们包含。所有 1xx(信息)、204(无内容)和 304(未修改)响应不得包含消息正文。所有其他响应都包含消息体,尽管它的长度可能为零。

4.4 消息长度

消息的传输长度是消息中出现的消息体的长度;也就是说,在应用了任何传输编码之后。当消息中包含消息正文时,该正文的传输长度由以下之一确定(按优先顺序):

   1.任何“MUST NOT”包含消息体的响应消息(例如 1xx、204 和 304 响应以及对 HEAD 请求的任何响应)总是由头字段之后的第一个空行终止,无论消息中存在的实体头字段。

   2.如果存在 Transfer-Encoding 标头字段(第 14.41 节)并且具有除“identity”以外的任何值,则使用“分块”传输编码(第 3.6 节)定义传输长度,除非消息通过关闭连接终止。

   3.如果存在 Content-Length 头字段(第 14.13 节),则其在 OCTET 中的十进制值表示实体长度和传输长度。如果这两个长度不同(即,如果存在 Transfer-Encoding 头字段),则不得发送 Content-Length 头字段。如果接收到的消息同时带有 Transfer-Encoding 头字段和 Content-Length 头字段,则必须忽略后者。

   4.如果消息使用媒体类型“multipart/byteranges”,并且没有另外指定传输长度,则该自限媒体类型定义传输长度。除非发送者知道接收者可以访问它,否则不得使用此媒体类型;来自 1.1 客户端的具有多个字节范围说明符的 Range 标头的请求中的存在意味着客户端可以解析 multipart/byteranges 响应。

范围标头可能由不理解 multipart/byteranges 的 1.0 代理转发;在这种情况下,服务器必须使用本节第 1,3 或 5 项中定义的方法来分隔消息。

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

为了与 HTTP/1.0 应用程序兼容,包含消息体的 HTTP/1.1 请求必须包含有效的 Content-Length 头字段,除非已知服务器符合 HTTP/1.1。如果请求包含消息体并且没有给出 Content-Length,如果服务器无法确定消息的长度,则应该以 400(错误请求)响应,或者如果它希望坚持使用 411(长度需要)响应接收有效的内容长度。

所有接收实体的 HTTP/1.1 应用程序必须接受“分块”传输编码(第 3.6 节),从而允许在无法提前确定消息长度时将这种机制用于消息。

消息不得同时包含 Content-Length 头字段和非身份传输编码(non-identity transfer-coding). 如果消息确实包含非身份传输编码,则必须忽略 Content-Length。

当在允许消息体的消息中给出 Content-Length 时,其字段值必须与消息体中的八位字节数完全匹配。 HTTP/1.1 用户代理必须在收到和检测到无效长度时通知用户。

4.5 通用头域

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

      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

只有结合协议版本的更改,才能可靠地扩展通用头字段名称。 但是,如果通信中的所有各方都将它们识别为通用头字段,则可以为新的或实验性的头字段赋予通用头字段的语义。 无法识别的标题字段被视为实体标题字段。

5 请求

从客户端到服务器的请求消息在该消息的第一行中包括要应用于资源的方法、资源的标识符以及正在使用的协议版本。

        Request       = Request-Line              ; Section 5.1
                        *(( general-header        ; Section 4.5
                         | request-header         ; Section 5.3
                         | entity-header ) CRLF)  ; Section 7.1
                        CRLF
                        [ message-body ]          ; Section 4.3

5.1 请求行

Request-Line 以方法标记开始,接着是 Request-URI 和协议版本,并以 CRLF 结束。 元素由 SP 字符分隔。 除了最后的 CRLF 序列外,不允许使用 CR 或 LF。

         请求行 = 方法 SP 请求 - URI SP HTTP - 版本 CRLF

5.1.1 方法

Method 标记指示要对由 Request-URI 标识的资源执行的方法。 该方法区分大小写。

       Method         = "OPTIONS"                ; Section 9.2
                      | "GET"                    ; Section 9.3
                      | "HEAD"                   ; Section 9.4
                      | "POST"                   ; Section 9.5
                      | "PUT"                    ; Section 9.6
                      | "DELETE"                 ; Section 9.7
                      | "TRACE"                  ; Section 9.8
                      | "CONNECT"                ; Section 9.9
                      | extension-method
       extension-method = token

资源允许的方法列表可以在 Allow 标头字段中指定(第 14.7 节)。响应的返回代码始终通知客户端当前是否允许在资源上使用方法,因为允许的方法集可以动态更改。如果源服务器知道该方法但请求的资源不允许该方法,则源服务器应该返回状态代码 405(方法不允许),如果源服务器无法识别或未实现该方法,则返回 501(未实现)。所有通用服务器都必须支持方法 GET 和 HEAD。所有其他方法都是可选的;但是,如果实现了上述方法,则必须使用与第 9 节中指定的语义相同的语义来实现它们。

5.1.2 请求-URI

Request-URI 是一个统一资源标识符(第 3.2 节),它标识了应用请求的资源。

       请求 URI = "*" |绝对URI | abs_path |权威

(Request-URI    = "*" | absoluteURI | abs_path | authority)

Request-URI 的四个选项取决于请求的性质。星号“*”表示请求并不适用于特定资源,而是适用于服务器本身,并且仅在使用的方法不一定适用于资源时才允许。一个例子是

       OPTIONS * HTTP/1.1

当向代理发出请求时,absoluteURI 形式是必需的。请求代理从有效缓存中转发请求或为其提供服务,并返回响应。请注意,代理可以将请求转发到另一个代理或直接转发到由 absoluteURI 指定的服务器。为了避免请求循环,代理必须能够识别其所有服务器名称,包括任何别名、本地变体和数字 IP 地址。一个示例请求行将是:

       GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

为了允许在 HTTP 的未来版本中的所有请求中转换为 absoluteURIs,所有 HTTP/1.1 服务器必须在请求中接受 absoluteURI 形式,即使 HTTP/1.1 客户端只会在对代理的请求中生成它们。

授权表格仅由 CONNECT 方法使用(第 9.9 节)。

Request-URI 最常见的形式是用于标识源服务器或网关上的资源。在这种情况下,URI 的绝对路径必须作为 Request-URI 传输(参见第 3.2.1 节,abs_path),并且 URI(授权)的网络位置必须在 Host 头字段中传输。例如,希望直接从源服务器检索上述资源的客户端将创建到主机“www.w3.org”的端口 80 的 TCP 连接并发送以下行:

       GET /pub/WWW/TheProject.html HTTP/1.1

       Host:www.w3.org

然后是请求的其余部分。注意绝对路径不能为空;如果原始 URI 中不存在任何内容,则必须将其指定为“/”(服务器根目录)。

Request-URI 以第 3.2.1 节中指定的格式传输。如果使用“% HEX HEX”编码 [42] 对 Request-URI 进行编码,则源服务器必须解码 Request-URI 以正确解释请求。服务器应该使用适当的状态码来响应无效的请求 URI。

透明代理在将接收到的 Request-URI 转发到下一个入站服务器时不得重写“abs_path”部分,除非如上所述用“/”替换空 abs_path。

注意:“不重写”规则可防止代理在源服务器不正确地将非保留 URI 字符用于保留目的时更改请求的含义。实现者应该知道一些 HTTP/1.1 之前的代理已经知道会重写 Request-URI。

5.2 请求标识的资源

Internet 请求所标识的确切资源是通过检查 Request-URI 和 Host 标头字段来确定的。

当确定由 HTTP/1.1 请求标识的资源时,不允许资源因请求的主机而异的源服务器可以忽略主机头字段值。 (但有关 HTTP/1.1 中主机支持的其他要求,请参阅第 19.6.1.1 节。)

根据请求的主机(有时称为虚拟主机或虚主机名)区分资源的源服务器必须使用以下规则来确定 HTTP/1.1 请求中请求的资源:

   1. 如果 Request-URI 是 absoluteURI,则主机是 Request-URI 的一部分。请求中的任何主机头字段值都必须被忽略。

   2. 如果Request-URI不是absoluteURI,并且请求中包含Host头部字段,则主机由Host头部字段值确定。

   3. 如果由规则 1 或 2 确定的主机不是服务器上的有效主机,则响应必须是 400(错误请求)错误消息。

缺少 Host 头部字段的 HTTP/1.0 请求的接收者可以尝试使用启发式方法(例如,检查 URI 路径以查找特定主机的唯一内容)以确定正在请求的确切资源。

5.3 请求头域

请求头字段允许客户端将有关请求以及客户端本身的附加信息传递给服务器。这些字段充当请求修饰符,其语义等同于编程语言方法调用上的参数。

        request-header = Accept                   ; Section 14.1
                      | Accept-Charset           ; Section 14.2
                      | Accept-Encoding          ; Section 14.3
                      | Accept-Language          ; Section 14.4
                      | Authorization            ; Section 14.8
                      | Expect                   ; Section 14.20
                      | From                     ; Section 14.22
                      | Host                     ; Section 14.23
                      | If-Match                 ; Section 14.24
                      | If-Modified-Since        ; Section 14.25
                      | If-None-Match            ; Section 14.26
                      | If-Range                 ; Section 14.27
                      | If-Unmodified-Since      ; Section 14.28
                      | Max-Forwards             ; Section 14.31
                      | Proxy-Authorization      ; Section 14.34
                      | Range                    ; Section 14.35
                      | Referer                  ; Section 14.36
                      | TE                       ; Section 14.39
                      | User-Agent               ; Section 14.43

只有结合协议版本的更改,才能可靠地扩展请求头字段名称。 但是,如果通信中的所有各方都将它们识别为请求头字段,则可以为新的或实验性的头字段赋予请求头字段的语义。 无法识别(Unrecognized) 的头部字段被视为实体头部字段。

6 回应

在接收并解释请求消息后,服务器以 HTTP 响应消息进行响应。

         Response      = Status-Line               ; Section 6.1
                       *(( general-header        ; Section 4.5
                        | response-header        ; Section 6.2
                        | entity-header ) CRLF)  ; Section 7.1
                       CRLF
                       [ message-body ]          ; Section 7.2

6.1 状态行

响应消息的第一行是状态行,由协议版本和数字状态代码及其相关的文本短语组成,每个元素由 SP 字符分隔。除了最后的 CRLF 序列外,不允许使用 CR 或 LF。

       状态行 = HTTP- 版本 SP 状态- 代码 SP 原因- 短语 CRLF

6.1.1 状态码和原因短语

Status-Code 元素是尝试理解和满足请求的 3 位整数结果代码。这些代码在第 10 节中完全定义。原因短语旨在给出状态代码的简短文本描述。状态代码供自动机使用,原因短语供人类用户使用。客户不需要检查或显示原因短语。

状态码的第一个数字定义了响应的类别。最后两位数字没有任何分类作用。第一个数字有 5 个值:

      - 1xx:信息性 - 收到请求,继续处理

      - 2xx: Success - 操作被成功接收、理解和接受

      - 3xx:重定向 - 必须采取进一步行动才能完成请求

      - 4xx:客户端错误 - 请求包含错误语法或无法完成

      - 5xx: 服务器错误 - 服务器未能完成一个明显有效的请求

下面介绍了为 HTTP/1.1 定义的数字状态代码的各个值,以及一组相应的原因短语的示例。此处列出的原因短语只是建议——它们可以被本地等效替换而不影响协议。

      状态码 =

            “100”;第 10.1.1 节:继续 Continue

          | “101”;第 10.1.2 节:交换协议 Switching Protocols

          | “200”;第 10.2.1 节:OK

          | “201”;第 10.2.2 节:创建 Created

          | “202”;第 10.2.3 节:接受 Accepted

          | “203”;第 10.2.4 节:非权威信息 Non-Authoritative Information

          | “204”;第 10.2.5 节:无内容 No Content

          | “205”;第 10.2.6 节:重置内容 Reset Content

          | “206”;第 10.2.7 节:部分内容 Partial Content

          | “300”;第 10.3.1 节:多项选择 Multiple Choices

          | “301”;第 10.3.2 节:永久移动 Moved Permanently

          | “302”;第 10.3.3 节:找到 Found

          | “303”;第 10.3.4 节:见其他 See Other

          | “304”;第 10.3.5 节:未修改 Not Modified

          | “305”;第 10.3.6 节:使用代理 Use Proxy

          | “307”;第 10.3.8 节:临时重定向 Temporary Redirect

          | “400”;第 10.4.1 节:错误请求 Bad Request

          | “401”;第 10.4.2 节:未经授权 Unauthorized

          | “402”;第 10.4.3 节:需要付款 Payment Required

          | “403”;第 10.4.4 节:禁止 Forbidden

          | “404”;第 10.4.5 节:未找到 Not Found

          | “405”;第 10.4.6 节:不允许的方法 Method Not Allowed

          | “406”;第 10.4.7 节:不可接受 Not Acceptable

          | “407”;第 10.4.8 节:需要代理身份验证 Proxy Authentication Required

          | “408”;第 10.4.9 节:请求超时 Request Time-out

          | “409”;第 10.4.10 节:冲突 Conflict

          | “410”;第 10.4.11 节:消失了 Gone

          | “411”;第 10.4.12 节:所需长度 Length Required

          | “412”;第 10.4.13 节:前提条件失败 Precondition Failed

          | “413”;第 10.4.14 节:请求实体太大 Request Entity Too Large

          | “414”;第 10.4.15 节:请求 URI 太大 Request-URI Too Large

          | “415”;第 10.4.16 节:不支持的媒体类型 Unsupported Media Type

          | “416”;第 10.4.17 节:请求的范围不可满足 Requested range not satisfiable

          | “417”;第 10.4.18 节:预期失败 Expectation Failed

          | “500”;第 10.5.1 节:内部服务器错误 Internal Server Error

          | “501”;第 10.5.2 节:未实施 Not Implemented

          | “502”;第 10.5.3 节:错误网关 Bad Gateway

          | “503”;第 10.5.4 节:服务不可用 Service Unavailable

          | “504”;第 10.5.5 节:网关超时 Gateway Time-out

          | “505”;第 10.5.6 节:不支持 HTTP 版本 HTTP Version not supported

          |扩展代码

      扩展代码 = 3DIGIT

      原因-短语 = *<TEXT,不包括 CR、LF>

HTTP 状态代码是可扩展的。 HTTP 应用程序不需要理解所有注册状态码的含义,尽管这样的理解显然是可取的。但是,应用程序必须理解任何状态代码的类别,如第一个数字所示,并将任何无法识别的响应视为等同于该类别的 x00 状态代码,但不得缓存无法识别的响应。例如,如果客户端收到无法识别的状态码 431,它可以安全地假定其请求有问题,并将响应视为收到 400 状态码。在这种情况下,用户代理应该向用户呈现与响应一起返回的实体,因为该实体可能包含人类可读的信息,这些信息将解释异常状态。

6.2 响应头域

response-header 字段允许服务器传递有关无法放置在状态行中的响应的附加信息。 这些标头字段提供有关服务器的信息以及有关对由 Request-URI 标识的资源的进一步访问的信息。

       response-header = Accept-Ranges           ; Section 14.5
                       | Age                     ; Section 14.6
                       | ETag                    ; Section 14.19
                       | Location                ; Section 14.30
                       | Proxy-Authenticate      ; Section 14.33
                       | Retry-After             ; Section 14.37
                       | Server                  ; Section 14.38
                       | Vary                    ; Section 14.44
                       | WWW-Authenticate        ; Section 14.47

只有结合协议版本的更改,才能可靠地扩展响应头字段名称。但是,如果通信中的所有各方都将它们识别为响应头字段,则可以为新的或实验性的头字段赋予响应头字段的语义。无法识别的标题字段被视为实体标题字段。

7 实体

如果不受请求方法或响应状态代码的限制,请求和响应消息可以传输实体。实体由实体头字段和实体主体组成,尽管某些响应仅包含实体头。

在本节中,发送者和接收者都指客户端或服务器,具体取决于谁发送和谁接收实体。

7.1 实体头字段

实体标头字段定义有关实体主体的元信息,或者,如果没有主体,则定义有关请求标识的资源的元信息。其中一些元信息是可选的;本规范的某些部分可能需要一些。

       entity-header  = Allow                    ; Section 14.7
                      | Content-Encoding         ; Section 14.11
                      | Content-Language         ; Section 14.12
                      | Content-Length           ; Section 14.13
                      | Content-Location         ; Section 14.14
                      | Content-MD5              ; Section 14.15
                      | Content-Range            ; Section 14.16
                      | Content-Type             ; Section 14.17
                      | Expires                  ; Section 14.21
                      | Last-Modified            ; Section 14.29
                      | extension-header
       extension-header = message-header

扩展头机制允许在不改变协议的情况下定义额外的实体头字段,但不能假设这些字段可以被接收者识别。无法识别的头部字段应该被接收者忽略并且必须被透明代理转发。

7.2 实体

与 HTTP 请求或响应一起发送的实体主体(如果有)采用实体标头字段定义的格式和编码。

       实体主体 = *OCTET

如第 4.3 节所述,仅当存在消息主体时,实体主体才会出现在消息中。实体主体是通过对可能已应用的任何传输编码进行解码从消息主体中获得的,以确保消息的安全和正确传输。

7.2.1 类型

当消息中包含实体主体时,该主体的数据类型是通过头部字段 Content-Type 和 Content-Encoding 确定的。这些定义了一个两层的有序编码模型:

       实体主体:=内容编码(内容类型(数据))

Content-Type 指定底层数据的媒体类型。 Content-Encoding 可用于指示应用于数据的任何附加内容编码,通常用于数据压缩,这是所请求资源的属性。没有默认编码。

任何包含实体主体的 HTTP/1.1 消息都应该包含定义该主体的媒体类型的 Content-Type 头字段。当且仅当媒体类型不是由 Content-Type 字段给出时,接收者可以尝试通过检查其内容和/或用于识别资源的 URI 的名称扩展来猜测媒体类型。如果媒体类型仍然未知,接收者应该将其视为类型“application/octet-stream”。

7.2.2 实体长度

消息的实体长度是在应用任何传输编码之前消息正文的长度。第 4.4 节定义了如何确定消息体的传输长度。

【Part2 从第8节-“连接”开始】

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值