9. Methods (方法)
9.1. Overview (概述)
请求方法令牌是请求语义的主要来源; 它指示客户端发出此请求的目的以及客户端期望的成功结果.
请求方法的语义可能会被请求中存在的某些头部字段的语义进一步特化,如果这些附加语义不与方法冲突. 例如,客户端可以发送条件请求头部字段(第13.1节)以使请求的操作取决于目标资源的当前状态.
HTTP被设计为可用作分布式对象系统的接口. 请求方法调用要应用于目标资源的操作,其方式与远程方法调用可以发送到标识的对象的方式非常相似.
method = token
方法令牌区分大小写,因为它可能用作具有区分大小写的方法名称的基于对象的系统的网关. 按照惯例,标准化方法以全大写US-ASCII字母定义.
与分布式对象不同,HTTP中的标准化请求方法不是特定于资源的,因为统一接口为基于网络的系统提供了更好的可见性和重用性[REST]. 一旦定义,标准化方法在应用于任何资源时应该具有相同的语义,尽管每个资源自己确定这些语义是否被实现或允许.
本规范定义了许多HTTP中常用的标准化方法,如下表所述.
| 方法名称 | 描述 | 章节 |
|---|---|---|
| GET | 传输目标资源的当前表示. | 9.3.1 |
| HEAD | 与GET相同,但不传输响应内容. | 9.3.2 |
| POST | 对请求内容执行特定于资源的处理. | 9.3.3 |
| PUT | 用请求内容替换目标资源的所有当前表示. | 9.3.4 |
| DELETE | 删除目标资源的所有当前表示. | 9.3.5 |
| CONNECT | 建立到由目标资源标识的服务器的隧道. | 9.3.6 |
| OPTIONS | 描述目标资源的通信选项. | 9.3.7 |
| TRACE | 沿着到目标资源的路径执行消息环回测试. | 9.3.8 |
所有通用服务器必须 (MUST) 支持GET和HEAD方法. 所有其他方法都是可选的 (OPTIONAL).
目标资源允许的方法集可以在Allow头部字段(第10.2.1节)中列出. 然而,允许的方法集可以动态更改. 接收到无法识别或未实现的请求方法的源服务器应该 (SHOULD) 以501(Not Implemented)状态码响应. 接收到已识别和已实现但目标资源不允许的请求方法的源服务器应该 (SHOULD) 以405(Method Not Allowed)状态码响应.
本规范范围之外的其他方法已被指定用于HTTP. 所有此类方法都应该在"超文本传输协议(HTTP)方法注册表"中注册,如第16.1节所述.
9.2. Common Method Properties (通用方法属性)
9.2.1. Safe Methods (安全方法)
如果请求方法的定义语义本质上是只读的,则认为它们是"安全的" (safe); 即,客户端不请求也不期望由于将安全方法应用于目标资源而在源服务器上发生任何状态更改. 同样,合理使用安全方法不应该造成任何伤害,财产损失或对源服务器造成异常负担.
安全方法的这一定义并不阻止实现包括可能有害的,不完全只读的或在调用安全方法时引起副作用的行为. 然而,重要的是,客户端没有请求该附加行为,也不能对其负责. 例如,大多数服务器在每个响应完成时将请求信息附加到访问日志文件,无论方法如何,即使日志存储可能已满并导致服务器失败,这也被认为是安全的. 同样,通过在Web上选择广告发起的安全请求通常会产生向广告帐户收费的副作用.
在本规范定义的请求方法中,GET,HEAD,OPTIONS和TRACE方法被定义为安全的.
区分安全和不安全方法的目的是允许自动检索过程(蜘蛛)和缓存性能优化(预取)在不担心造成伤害的情况下工作. 此外,它允许用户代理在处理可能不受信任的内容时对不安全方法的自动使用应用适当的约束.
用户代理在向用户呈现潜在操作时应该 (SHOULD) 区分安全和不安全方法,以便可以在请求不安全操作之前使用户意识到该操作.
当资源被构造为使得目标URI中的参数具有选择操作的效果时,资源所有者有责任确保该操作与请求方法语义一致. 例如,基于Web的内容编辑软件通常在查询参数中使用操作,例如"page?do=delete". 如果此类资源的目的是执行不安全操作,则当使用安全请求方法访问它时,资源所有者必须 (MUST) 禁用或不允许该操作. 如果不这样做,当自动过程为了链接维护,预取,构建搜索索引等目的对每个URI引用执行GET时,将导致不幸的副作用.
9.2.2. Idempotent Methods (幂等方法)
如果使用该方法的多个相同请求对服务器的预期效果与单个此类请求的效果相同,则认为请求方法是"幂等的" (idempotent). 在本规范定义的请求方法中,PUT,DELETE和安全请求方法是幂等的.
与安全的定义一样,幂等属性仅适用于用户请求的内容; 服务器可以自由地单独记录每个请求,保留修订控制历史记录,或为每个幂等请求实现其他非幂等副作用.
幂等方法之所以被区分,是因为如果在客户端能够读取服务器的响应之前发生通信故障,则可以自动重复该请求. 例如,如果客户端发送PUT请求并且在接收到任何响应之前底层连接关闭,则客户端可以建立新连接并重试幂等请求. 它知道重复请求将具有相同的预期效果,即使原始请求成功,尽管响应可能不同.
客户端不应该 (SHOULD NOT) 自动重试具有非幂等方法的请求,除非它有某种方法知道请求语义实际上是幂等的(无论方法如何),或者有某种方法检测到原始请求从未被应用.
例如,如果用户代理知道(通过设计或配置)该资源的请求是安全的,则它可以自动重复POST请求. 同样,专门设计用于在版本控制存储库上操作的用户代理可能能够通过在连接失败后检查目标资源修订版,恢复或修复任何部分应用的更改,然后自动重试失败的请求来从部分故障条件中恢复.
一些客户端采取更冒险的方法并尝试猜测何时可能自动重试. 例如,如果在接收到响应的任何部分之前底层传输连接关闭,客户端可能会自动重试POST请求,特别是如果使用了空闲的持久连接.
代理不得 (MUST NOT) 自动重试非幂等请求. 客户端不应该 (SHOULD NOT) 自动重试失败的自动重试.
9.2.3. Methods and Caching (方法和缓存)
为了使缓存存储和使用响应,关联的方法需要明确允许缓存并详细说明在什么条件下可以使用响应来满足后续请求; 不这样做的方法定义不能被缓存. 有关其他要求,请参阅[CACHING].
本规范为GET,HEAD和POST定义了缓存语义,尽管绝大多数缓存实现仅支持GET和HEAD.
9.3. Method Definitions (方法定义)
9.3.1. GET
GET方法请求传输目标资源的当前所选表示. 成功的响应反映了由目标URI标识的"相同性"质量([URI]的第1.2.2节). 因此,通过HTTP检索可识别信息通常通过对与在200(OK)响应中提供该信息的潜力相关联的标识符进行GET请求来执行.
GET是信息检索的主要机制,也是几乎所有性能优化的焦点. 为每个重要资源生成URI的应用程序可以从这些优化中受益,同时使其他应用程序能够重用它们,从而创建促进Web进一步扩展的网络效应.
很容易将资源标识符视为远程文件系统路径名,并将表示视为此类文件内容的副本. 事实上,许多资源就是这样实现的(有关相关安全注意事项,请参阅第17.3节). 然而,实际上没有这样的限制.
资源的HTTP接口同样可能被实现为内容对象树,各种数据库记录的编程视图或其他信息系统的网关. 即使URI映射机制与文件系统绑定,源服务器也可能被配置为将请求作为输入执行文件并将输出作为表示发送,而不是直接传输文件. 无论如何,只有源服务器需要知道每个资源标识符如何对应于实现以及该实现如何管理选择和发送目标资源的当前表示.
客户端可以通过在请求中发送Range头部字段(第14.2节)将GET的语义更改为"范围请求",仅请求传输所选表示的某些部分.
尽管请求消息帧与使用的方法无关,但在GET请求中接收的内容没有一般定义的语义,不能更改请求的含义或目标,并且可能导致某些实现拒绝请求并关闭连接,因为它作为请求走私攻击的潜力([HTTP/1.1]的第11.2节). 客户端不应该 (SHOULD NOT) 在GET请求中生成内容,除非它直接向先前指示(带内或带外)此类请求具有目的并将得到充分支持的源服务器发出. 源服务器不应该 (SHOULD NOT) 依赖私有协议来接收内容,因为HTTP通信的参与者通常不知道请求链上的中间人.
对GET请求的响应是可缓存的; 缓存可以 (MAY) 使用它来满足后续的GET和HEAD请求,除非Cache-Control头部字段另有指示([CACHING]的第5.2节).
当使用从用户提供的信息构造目标URI的机制执行信息检索时,例如使用GET的表单的查询字段,可能会提供不适合在URI内公开的潜在敏感数据(参见第17.9节). 在某些情况下,可以过滤或转换数据,使其不会泄露此类信息. 在其他情况下,特别是当从缓存响应中没有好处时,使用POST方法(第9.3.3节)而不是GET可以在请求内容而不是目标URI中传输此类信息.
9.3.2. HEAD
HEAD方法与GET相同,只是服务器不得 (MUST NOT) 在响应中发送内容. HEAD用于获取有关所选表示的元数据,而无需传输其表示数据,通常用于测试超文本链接或查找最近的修改.
服务器应该 (SHOULD) 在对HEAD请求的响应中发送与请求方法是GET时将发送的相同头部字段. 然而,服务器可以 (MAY) 省略仅在生成内容时确定值的头部字段. 例如,某些服务器缓冲对GET的动态响应,直到生成最少量的数据,以便它们可以更有效地分隔小响应或就内容选择做出延迟决策. 对GET的此类响应可能包含Content-Length和Vary字段,例如,这些字段不在HEAD响应中生成. 这些小的不一致性被认为优于为HEAD请求生成和丢弃内容,因为HEAD通常是为了效率而请求的.
尽管请求消息帧与使用的方法无关,但在HEAD请求中接收的内容没有一般定义的语义,不能更改请求的含义或目标,并且可能导致某些实现拒绝请求并关闭连接,因为它作为请求走私攻击的潜力([HTTP/1.1]的第11.2节). 客户端不应该 (SHOULD NOT) 在HEAD请求中生成内容,除非它直接向先前指示(带内或带外)此类请求具有目的并将得到充分支持的源服务器发出. 源服务器不应该 (SHOULD NOT) 依赖私有协议来接收内容,因为HTTP通信的参与者通常不知道请求链上的中间人.
对HEAD请求的响应是可缓存的; 缓存可以 (MAY) 使用它来满足后续的HEAD请求,除非Cache-Control头部字段另有指示([CACHING]的第5.2节). HEAD响应也可能影响先前缓存的对GET的响应; 请参阅[CACHING]的第4.3.5节.
9.3.3. POST
POST方法请求目标资源根据资源自己的特定语义处理请求中包含的表示. 例如,POST用于以下功能(以及其他功能):
- 向数据处理过程提供数据块,例如输入到HTML表单中的字段;
- 将消息发布到公告板,新闻组,邮件列表,博客或类似的文章组;
- 创建源服务器尚未标识的新资源; 以及
- 将数据附加到资源的现有表示.
源服务器通过根据处理POST请求的结果选择适当的状态码来指示响应语义; 本规范定义的几乎所有状态码都可以在对POST的响应中接收(例外是206(Partial Content),304(Not Modified)和416(Range Not Satisfiable)).
如果由于成功处理POST请求而在源服务器上创建了一个或多个资源,则源服务器应该 (SHOULD) 发送201(Created)响应,其中包含提供所创建主要资源的标识符的Location头部字段(第10.2.2节)以及描述请求状态同时引用新资源的表示.
只有当POST响应包含明确的新鲜度信息(参见[CACHING]的第4.2.1节)和与POST的目标URI具有相同值的Content-Location头部字段(第8.7节)时,对POST请求的响应才可缓存. 缓存的POST响应可以重用以满足以后的GET或HEAD请求. 相反,POST请求不能由缓存的POST响应满足,因为POST可能不安全; 请参阅[CACHING]的第4节.
如果处理POST的结果等同于现有资源的表示,则源服务器可以 (MAY) 通过发送带有Location字段中现有资源标识符的303(See Other)响应将用户代理重定向到该资源. 这具有向用户代理提供资源标识符并通过更适合共享缓存的方法传输表示的好处,尽管如果用户代理尚未缓存表示,则需要额外的请求.
9.3.4. PUT
PUT方法请求使用请求消息内容中包含的表示定义的状态创建或替换目标资源的状态. 成功PUT给定表示将表明对该相同目标资源的后续GET将导致在200(OK)响应中发送等效表示. 然而,不能保证这种状态更改是可观察的,因为目标资源可能在接收到任何后续GET之前被其他用户代理并行操作,或者可能受到源服务器的动态处理. 成功的响应仅意味着用户代理的意图在源服务器处理时实现了.
如果目标资源没有当前表示并且PUT成功创建了一个,则源服务器必须 (MUST) 通过发送201(Created)响应通知用户代理. 如果目标资源确实具有当前表示,并且该表示根据所包含表示的状态成功修改,则源服务器必须 (MUST) 发送200(OK)或204(No Content)响应以指示请求成功完成.
源服务器应该 (SHOULD) 验证PUT表示与其为目标资源配置的约束一致. 例如,如果源服务器根据URI确定资源的表示元数据,则源服务器需要确保在成功的PUT请求中接收的内容与该元数据一致. 当PUT表示与目标资源不一致时,源服务器应该 (SHOULD) 通过转换表示或更改资源配置使它们一致,或者用包含足够信息以解释为什么表示不合适的适当错误消息响应. 建议使用409(Conflict)或415(Unsupported Media Type)状态码,后者特定于Content-Type值的约束.
例如,如果目标资源配置为始终具有"text/html"的Content-Type,并且正在PUT的表示具有"image/jpeg"的Content-Type,则源服务器应该执行以下操作之一:
a. 重新配置目标资源以反映新的媒体类型; b. 在将PUT表示保存为新资源状态之前将其转换为与资源一致的格式; 或者, c. 拒绝带有415(Unsupported Media Type)响应的请求,指示目标资源仅限于"text/html",可能包括指向适合新表示的不同资源的链接.
HTTP没有准确定义PUT方法如何影响源服务器的状态,超出了用户代理请求的意图和源服务器响应的语义所能表达的范围. 它没有以该词的任何意义定义资源可能是什么. 它没有定义如何"存储"资源状态,也没有定义此类存储如何因资源状态的更改而更改,也没有定义源服务器如何将资源状态转换为表示. 一般来说,资源接口后面的所有实现细节都被服务器有意隐藏.
这扩展到如何存储头部和尾部字段; 虽然像Content-Type这样的常见头部字段通常会被存储并在后续GET请求时返回,但头部和尾部字段处理特定于接收请求的资源. 因此,源服务器应该 (SHOULD) 忽略在PUT请求中接收到的无法识别的头部和尾部字段(即,不将它们保存为资源状态的一部分).
源服务器不得 (MUST NOT) 在对PUT的成功响应中发送验证器字段(第8.8节),例如ETag或Last-Modified字段,除非请求的表示数据在未对内容应用任何转换的情况下保存(即,资源的新表示数据与PUT请求中接收的内容相同)并且验证器字段值反映新表示. 此要求允许用户代理知道它发送(并保留在内存中)的表示是PUT的结果,因此不需要再次从源服务器检索它. 响应中接收到的新验证器可用于将来的条件请求,以防止意外覆盖(第13.1节).
POST和PUT方法之间的根本区别由所包含表示的不同意图突出显示. POST请求中的目标资源旨在根据资源自己的语义处理所包含的表示,而PUT请求中的所包含表示被定义为替换目标资源的状态. 因此,PUT的意图是幂等的并且对中间人可见,即使确切的效果仅由源服务器知道.
正确解释PUT请求假定用户代理知道需要哪个目标资源. 在接收到状态更改请求后代表客户端选择适当URI的服务应该使用POST方法而不是PUT来实现. 如果源服务器不会对目标资源进行请求的PUT状态更改,而是希望将其应用于不同的资源,例如当资源已移动到不同的URI时,则源服务器必须 (MUST) 发送适当的3xx(Redirection)响应; 然后用户代理可以 (MAY) 就是否重定向请求做出自己的决定.
应用于目标资源的PUT请求可能对其他资源产生副作用. 例如,文章可能具有用于标识"当前版本"(资源)的URI,该URI与标识每个特定版本(不同资源,在某个时间点与当前版本资源共享相同状态)的URI分开. 对"当前版本" URI的成功PUT请求因此可能会创建新的版本资源,除了更改目标资源的状态之外,还可能导致在相关资源之间添加链接.
一些源服务器支持使用Content-Range头部字段(第14.4节)作为请求修饰符来执行部分PUT,如第14.5节所述.
对PUT方法的响应不可缓存. 如果成功的PUT请求通过具有目标URI的一个或多个存储响应的缓存,则这些存储的响应将失效(参见[CACHING]的第4.4节).
9.3.5. DELETE
DELETE方法请求源服务器删除目标资源与其当前功能之间的关联. 实际上,此方法类似于UNIX中的"rm"命令: 它表示对源服务器的URI映射的删除操作,而不是期望先前关联的信息被删除.
如果目标资源具有一个或多个当前表示,它们可能会也可能不会被源服务器销毁,并且关联的存储可能会也可能不会被回收,这完全取决于资源的性质及其由源服务器的实现(这超出了本规范的范围). 同样,资源的其他实现方面可能需要由于DELETE而被停用或存档,例如数据库或网关连接. 通常,假定源服务器仅允许对其具有完成删除的规定机制的资源进行DELETE.
相对较少的资源允许DELETE方法——它的主要用途是远程创作环境,其中用户对其效果有一定的指导. 例如,先前使用PUT请求创建的资源,或在对POST请求的201(Created)响应后通过Location头部字段标识的资源,可能允许相应的DELETE请求撤消这些操作. 同样,实现创作功能的自定义用户代理实现,例如使用HTTP进行远程操作的修订控制客户端,可能基于假设服务器的URI空间已被设计为对应于版本存储库而使用DELETE.
如果成功应用DELETE方法,则源服务器应该 (SHOULD) 发送
- 202(Accepted)状态码,如果操作可能成功但尚未执行,
- 204(No Content)状态码,如果操作已执行且不提供进一步信息,或
- 200(OK)状态码,如果操作已执行且响应消息包括描述状态的表示.
尽管请求消息帧与使用的方法无关,但在DELETE请求中接收的内容没有一般定义的语义,不能更改请求的含义或目标,并且可能导致某些实现拒绝请求并关闭连接,因为它作为请求走私攻击的潜力([HTTP/1.1]的第11.2节). 客户端不应该 (SHOULD NOT) 在DELETE请求中生成内容,除非它直接向先前指示(带内或带外)此类请求具有目的并将得到充分支持的源服务器发出. 源服务器不应该 (SHOULD NOT) 依赖私有协议来接收内容,因为HTTP通信的参与者通常不知道请求链上的中间人.
对DELETE方法的响应不可缓存. 如果成功的DELETE请求通过具有目标URI的一个或多个存储响应的缓存,则这些存储的响应将失效(参见[CACHING]的第4.4节).
9.3.6. CONNECT
CONNECT方法请求接收者建立到由请求目标标识的目标源服务器的隧道,如果成功,则此后将其行为限制为在两个方向上盲目转发数据,直到隧道关闭. 隧道通常用于通过一个或多个代理创建端到端虚拟连接,然后可以使用TLS(传输层安全性,[TLS13])保护该连接.
CONNECT使用特殊形式的请求目标,此方法独有,仅由隧道目的地的主机和端口号组成,由冒号分隔. 没有默认端口; 即使CONNECT请求基于包含省略端口的权威组件的URI引用(第4.1节),客户端也必须 (MUST) 发送端口号. 例如,
CONNECT server.example.com:80 HTTP/1.1
Host: server.example.com
服务器必须 (MUST) 拒绝针对空或无效端口号的CONNECT请求,通常通过以400(Bad Request)状态码响应.
由于CONNECT更改了HTTP连接的请求/响应性质,特定的HTTP版本可能有不同的方式将其语义映射到协议的线格式.
CONNECT旨在用于对代理的请求. 接收者可以通过直接连接到请求目标标识的服务器来建立隧道,或者如果配置为使用另一个代理,则通过将CONNECT请求转发到下一个入站代理. 源服务器可以 (MAY) 接受CONNECT请求,但大多数源服务器不实现CONNECT.
任何2xx(Successful)响应表示发送者(和所有入站代理)将在响应头部区段之后立即切换到隧道模式; 在该头部区段之后接收的数据来自请求目标标识的服务器. 除成功响应之外的任何响应表示隧道尚未形成.
当隧道中间人检测到任一侧已关闭其连接时,隧道关闭: 中间人必须 (MUST) 尝试将来自关闭侧的任何未完成数据发送到另一侧,关闭两个连接,然后丢弃任何剩余的未传递数据.
代理身份验证可用于建立创建隧道的权限. 例如,
CONNECT server.example.com:443 HTTP/1.1
Host: server.example.com:443
Proxy-Authorization: basic aGVsbG86d29ybGQ=
建立到任意服务器的隧道存在重大风险,特别是当目的地是不用于Web流量的知名或保留TCP端口时. 例如,到"example.com:25"的CONNECT将建议代理连接到SMTP流量的保留端口; 如果允许,这可能会欺骗代理中继垃圾邮件. 支持CONNECT的代理应该 (SHOULD) 将其使用限制为一组有限的已知端口或可配置的安全请求目标列表.
服务器不得 (MUST NOT) 在对CONNECT的2xx(Successful)响应中发送任何Transfer-Encoding或Content-Length头部字段. 客户端必须 (MUST) 忽略在对CONNECT的成功响应中接收的任何Content-Length或Transfer-Encoding头部字段.
CONNECT请求消息没有内容. CONNECT请求消息的头部区段之后发送的数据的解释特定于使用的HTTP版本.
对CONNECT方法的响应不可缓存.
9.3.7. OPTIONS
OPTIONS方法请求有关目标资源可用的通信选项的信息,无论是在源服务器还是在中间中间人. 此方法允许客户端确定与资源关联的选项和/或要求,或服务器的能力,而不暗示资源操作.
带有星号("")作为请求目标(第7.1节)的OPTIONS请求通常适用于服务器,而不是特定资源. 由于服务器的通信选项通常取决于资源,因此""请求仅作为"ping"或"no-op"类型的方法有用; 它除了允许客户端测试服务器的能力之外什么都不做. 例如,这可以用于测试代理的HTTP/1.1一致性(或缺乏一致性).
如果请求目标不是星号,则OPTIONS请求适用于与目标资源通信时可用的选项.
生成对OPTIONS的成功响应的服务器应该 (SHOULD) 发送任何可能指示服务器实现的并适用于目标资源的可选功能的头部(例如,Allow),包括本规范未定义的潜在扩展. 响应内容(如果有)也可能以机器或人类可读的表示描述通信选项. 本规范未定义此类表示的标准格式,但可能由HTTP的未来扩展定义.
客户端可以 (MAY) 在OPTIONS请求中发送Max-Forwards头部字段以针对请求链中的特定接收者(参见第7.6.2节). 代理不得 (MUST NOT) 在转发请求时生成Max-Forwards头部字段,除非该请求是用Max-Forwards字段接收的.
生成包含内容的OPTIONS请求的客户端必须 (MUST) 发送描述表示媒体类型的有效Content-Type头部字段. 请注意,本规范没有定义此类内容的任何用途.
对OPTIONS方法的响应不可缓存.
9.3.8. TRACE
TRACE方法请求请求消息的远程应用程序级环回. 请求的最终接收者应该 (SHOULD) 将接收到的消息(排除下面描述的某些字段)作为200(OK)响应的内容反射回客户端. "message/http"格式([HTTP/1.1]的第10.1节)是一种这样做的方法. 最终接收者是源服务器或在请求中接收Max-Forwards值为零(0)的第一个服务器(第7.6.2节).
客户端不得 (MUST NOT) 在TRACE请求中生成可能被响应公开的敏感数据的字段. 例如,用户代理在TRACE请求中发送存储的用户凭据(第11节)或cookie [COOKIE]将是愚蠢的. 请求的最终接收者在生成响应内容时应该 (SHOULD) 排除任何可能包含敏感数据的请求字段.
TRACE允许客户端查看在请求链的另一端接收到的内容,并将该数据用于测试或诊断信息. Via头部字段(第7.6.3节)的值特别有趣,因为它充当请求链的跟踪. 使用Max-Forwards头部字段允许客户端限制请求链的长度,这对于测试以无限循环转发消息的代理链很有用.
客户端不得 (MUST NOT) 在TRACE请求中发送内容.
对TRACE方法的响应不可缓存.