Web API:使用POST还是PUT创建资源的新版本?
Web API:使用POST还是PUT创建资源的新版本?
背景信息分析:
根据RFC 2616, § 9.5,POST
用于创建资源:
POST方法用于请求原始服务器接受请求中封装的实体作为Request-Line中标识的资源的的新附属资源。
根据RFC 2616, § 9.6,PUT
用于创建或替换资源:
PUT方法会请求服务器存储请求中封装的实体在提供的Request-URI下。如果Request-URI指向已存在的资源,则封装的实体应该被视为居住在原始服务器上的已修改版本。如果Request-URI不指向现有的资源,并且该URI可以由请求的用户代理定义为新资源,则原始服务器可以使用该URI创建资源。
我的问题:
那么,应该使用哪个HTTP方法来创建资源?或者应该支持两种方法?
你可以在网上找到一些关于使用 HTTP 请求方法的断言:
但两种说法都不完全正确。
更好的方式是根据动作的幂等性选择使用 PUT 还是 POST。
PUT 表示将一个资源放置到指定的 URL,以不同的形式完全替换该 URL 上可用的任何内容。按照定义,PUT 是幂等的,可以执行任意多次,结果都是相同的。例如,x=5
是幂等的。不管资源之前是否存在,都可以执行 PUT(例如,为了创建或更新资源)!
POST 用于更新资源、添加子资源或引起更改。在这种方式下,POST 不是幂等的,就像 x++
不是幂等的一样。
基于这种论点,当你知道你要创建的资源的 URL 时,可以使用 PUT 进行创建。当你知道要创建的资源类型的“工厂”或管理器的 URL 时,可以使用 POST 进行创建。
所以:
POST /expense-report
或:
PUT /expense-report/10929
总体:
创建操作可以使用PUT和POST。
你需要问自己:"你在哪个对象上执行操作?"来区分你应该使用哪个。假设你在设计一个用于提问的API。如果你想使用POST,那么就是针对问题列表做操作。如果你想使用PUT,那么就是针对特定的问题做操作。
完美的,两者都可以使用,那么我在RESTful的设计中应该使用哪一个呢:
你不需要支持PUT和POST两种方式。
你使用哪种方式取决于你自己。但是要记住,在请求中,选择正确的方式取决于你所引用的对象是什么。
一些考虑因素:
- 你是否明确命名所创建的URL对象,还是让服务器自己决定?如果你命名,那么就使用PUT。如果你让服务器决定,那么就使用POST。
- PUT假定具有幂等性,因此如果你两次PUT相同的对象,则不会有额外的影响。这是一个很好的特性,所以我在可能的情况下会使用PUT。只需确保服务器正确实现了PUT的幂等性即可。
- 你可以使用相同的对象URL使用PUT更新或创建资源
- 使用POST时,你可以有两个请求同时对一个URL做修改,并且他们可以更新对象的不同部分。
一个示例:
作为我在另一个回答中的一部分,我写了以下内容:
POST:
用于修改和更新资源
POST /questions/HTTP/1.1 Host: www.example.com/
请注意以下错误:
POST /questions/HTTP/1.1 Host: www.example.com/
如果URL还没有创建,您不应该使用POST来创建它并指定名称。这应该会导致“资源未找到”错误,因为
还不存在。您应该首先将
资源PUT到服务器上。
但是,您可以通过以下方式使用POST创建资源:
POST /questions HTTP/1.1 Host: www.example.com/
请注意,在这种情况下,不指定资源名称,新对象的URL路径将返回给您。
PUT:
用于创建或覆盖资源,并指定资源的新URL。
对于新资源:
PUT /questions/HTTP/1.1 Host: www.example.com/
要覆盖现有资源:
PUT /questions/HTTP/1.1 Host: www.example.com/
此外,RFC 7231第4.3.4节PUT更简练地指出(重点添加),
4.3.4. PUT
PUT方法请求使用请求消息负载中的表示定义的状态
创建
或替换
目标资源的状态。