首页 > 解决方案 > 如果资源不存在,HTTP PUT 是否应该创建它?

问题描述

假设有人PUT对我的 endoint 执行请求:

/resources/{id}

但是,我的 PostgreSQL 数据库中没有存储具有给定 ID 的资源。

根据RFC 2616,如果我有能力,我应该创建资源:

PUT方法请求将封闭的实体存储在提供的 Request-URI 下。如果 Request-URI 引用了一个已经存在的资源,封闭的实体应该被认为是在源服务器上的一个修改版本。如果 Request-URI 不指向现有资源,并且该 URI 能够被请求用户代理定义为新资源,则源服务器可以使用该 URI 创建资源。

可以使用提供的 id 创建资源吗?因为在数据库插入上手动分配 id 不是最佳做法。

404如果无法创建资源,我应该返回错误吗?

标签: resthttpput

解决方案


首先,您使用的是一个过时的文档:RFC 2616 现在不再相关,任何使用此类文档作为参考的人都应该立即停止

引用在撰写本文时担任 IETF HTTP 和 QUIC 工作组联合主席的Mark Nottingham的话:

不要使用 RFC2616。从您的硬盘驱动器、书签中删除它,并刻录(或负责任地回收)任何打印出来的副本。

旧的 RFC 2616 已被以下文档取代,这些文档共同定义了 HTTP/1.1 协议:

如果您正在寻找方法、状态代码和标头定义,那么 RFC 7231是您应该参考的文档。


说了这么多,让我们回到你的问题。

PUT如果资源不存在,HTTP 是否应该创建它?

这取决于。

但是,如果您的应用程序代表客户端生成资源标识符,正如您在问题中提到的,那么您应该使用POST而不是PUT创建资源。

PUT下面引用了方法定义的某些部分。最后一句话似乎与您最相关(重点是我的),支持我刚才提到的内容:

4.3.4. 放

PUT方法请求目标资源的状态被创建或替换为请求消息有效负载中包含的表示定义的状态。[...]

如果目标资源没有当前的表示并且PUT成功地创建了一个,那么源服务器必须通过发送一个201(创建的)响应来通知用户代理。如果目标资源确实有当前表示并且该表示已根据封闭表示的状态成功修改,则源服务器必须发送200(OK)或204(No Content)响应以指示请求成功完成. [...]

对请求的正确解释PUT假定用户代理知道需要哪个目标资源。 代表客户端选择适当 URI 的服务,在接收到状态更改请求后,应该使用POST方法而不是PUT. [...]


404如果无法创建资源,我应该返回错误吗?

这似乎是要返回的准确状态代码,因为没有找到所请求资源的表示:

6.5.4. 404 未找到

404未找到)状态码表示源服务器没有找到目标资源的当前表示或不愿意透露存在的表示。[...]


现在,为了完整起见,请在下面找到有关POST方法定义的一些相关引用,这些引用应该用于在您的问题中描述的场景中创建资源:

4.3.3. 邮政

POST方法请求目标资源根据资源自身的特定语义处理请求中包含的表示。例如,POST用于以下功能(其中包括):

[...]

  • 创建尚未被源服务器识别的新资源;

[...]

如果由于成功处理POST请求而在源服务器上创建了一个或多个资源,则源服务器应该发送一个201(已创建)响应,其中包含一个Location头字段,该字段提供创建的主要资源的标识符和描述引用新资源时请求的状态。

201状态码表示已创建新资源,而标Location头指示新创建的资源所在的位置。如果没有Location提供标头,则客户端应假定资源由有效请求 URI 标识:

6.3.2. 201 已创建

( 201Created) 状态码表示请求已完成,并导致创建一个或多个新资源。请求创建的主要资源由Location响应中的标头字段标识,如果未Location收到任何字段,则由有效请求 URI 标识。[...]


推荐阅读