假设有人在我的endoint上执行
PUT
请求:
/resources/{id}
但是,在我的PostgreSQL数据库中没有存储具有给定id的资源。
根据 RFC 2616 ,如果我能够:
PUT
方法请求将封闭的实体存储在提供的Request-URI下。如果请求URI引用已存在的资源,则应将包含的实体视为驻留在源服务器上的实体的修改版本。如果请求URI不指向现有资源,并且该URI能够被请求用户代理定义为新资源,则源服务器可以使用该URI创建资源。
是否可以使用提供的id创建资源?因为在数据库插入时手动分配ids不是最佳实践。
如果无法创建资源,我是否应该返回
404
错误?
首先,您使用的是一个过时的文档:RFC2616如今已不再适用,任何使用此类文档作为参考的人都应该立即停止使用。
引用 Mark Nottingham 的话,他在撰写本文时是IETF HTTP和QUIC工作组的联合主席:
请勿使用RFC2616 。从你的硬盘驱动器,书签中删除它,并刻录(或负责任地回收)任何打印出来的副本。
旧的RFC 2616已被以下文档取代,这些文档共同定义了HTTP/1.1协议:
如果您正在寻找方法、状态代码和标头定义,那么 RFC 7231 是您应该参考的文档。
话虽如此,让我们回到你的问题上。
如果资源不存在,
PUT
是否应该创建资源?
那得看情况。
但是,如果您的应用程序代表客户端生成资源标识符,那么您应该使用
POST
而不是
PUT
来创建资源。
下面引用了
PUT
方法定义的某些部分。最后一句话似乎与你最相关(亮点是我的),支持我刚才提到的:
PUT
方法请求创建目标资源的状态,或者用请求消息有效负载中封装的表示定义的状态替换目标资源的状态。..。
如果目标资源没有当前表示,并且
PUT
成功地创建了一个表示,则源服务器必须通过发送
201
(Created)响应来通知用户代理。如果目标资源确实具有当前表示,并且根据所附表示的状态成功地修改了该表示,则源服务器必须发送
200
(OK)或
204
(No Content)响应,以指示请求成功完成。..。
对
PUT
请求的正确解释假定用户代理知道需要哪个目标资源。在接收到状态更改请求后,代表客户端选择适当URI的服务应该使用
POST
PUT
**
.**方法而不是
方法来实现
...
如果无法创建资源,是否应该返回
404
错误?
这似乎是要返回的准确状态代码,因为没有找到所请求资源的表示形式:
404
(Not Found)状态代码表示源服务器没有找到目标资源的当前表示,或者不愿意公开存在该表示。..。
现在,为了完整起见,在下面的
POST
方法定义中找到一些相关的引号,这些引号应该用于在您的问题中描述的场景中创建资源:
POST
方法请求目标资源根据资源自身的特定语义处理请求中包含的表示。例如,
POST
用于以下函数(以及其他函数):
..。
..。
如果作为成功处理
POST
请求的结果而在源服务器上创建了一个或多个资源,则源服务器应发送
201
( created )响应,其中包含
Location
报头字段,该字段提供所创建的主资源的标识符,以及在引用新资源时描述请求状态的表示。
201
状态代码指示已创建新资源,而
Location
标头指示新创建的资源所在的位置。如果未提供
Location
标头,则客户端应假定资源是由有效的请求URI标识的:
201
( created )状态代码指示请求已完成,并导致创建了一个或多个新资源。由请求创建的主资源由响应中的
Location
标头字段标识,或者,如果没有接收到
Location
字段,则由有效的请求URI标识。...
简而言之,这取决于您想要存储的有效负载是否违反了服务器对资源的任何约束。
一般而言,我认为它应该尝试这样做,因为客户端显式地表达了将该特定表示存储在目标URI中的意图。但是,服务器应该在此之前执行约束检查!通常,在真正的REST场景中,客户端应该使用服务器提供的URI,而不是自己选择任何URI。因此,服务器应该控制其名称空间,因此默认情况下不建议使用
PUT
创建资源。
话虽如此,由于
PUT
是幂等的,而
POST
不是,所以一些客户可能想要从这个属性中受益。在这里,
POST-PUT creation pattern
已经发展,客户端尝试通过
POST
创建新资源,直到它通过响应中的
Location
头接收到确认,然后尝试通过
PUT
更新该资源的状态。这样,客户端可以确保在传输问题的情况下,表示只创建了一次。根据不同的立场,有些人可能会将资源的实际更新视为实际的资源创建,尽管由于客户端预先收到了相应的链接,但情况并非如此。
请注意,如果服务器被配置为为某些URI端点提供特定的表示,则服务器也有权将表示转换为不同的内容。设想通过PUT将图像上传到URI,然后服务器将图像嵌入到HTML页面
这里嵌入了两个问题: 1)应该尝试创建资源,2)如果不能,会发生什么。
1) @cass链接的RFC表示 https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4
PUT方法请求创建目标资源的状态,或者用请求消息有效负载中包含的表示定义的状态替换目标资源的状态。给定表示的成功PUT将意味着在相同目标资源上的后续GET将导致在200 (OK)响应中发送等效的表示。
此外,Mozilla的文本 https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
HTTP PUT请求方法创建一个新资源,或者用请求有效负载替换目标资源的表示。
此外,从原始的RFC (被上面的测试替换) https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
PUT方法请求将封闭的实体存储在提供的Request-URI下。如果请求URI引用已存在的资源,则应将包含的实体视为驻留在源服务器上的实体的修改版本。如果请求URI不指向现有资源,并且该URI能够被请求用户代理定义为新资源,则源服务器可以使用该URI创建资源。
这有点轶事,但Kubernetes API也小心地进行了这种区分,并通知它的修补程序的用户,如果他们真的意味着更新: https://kubernetes.io/docs/reference/using-api/api-concepts/#api-verbs
对于PUT请求,Kubernetes根据现有对象的状态在内部将其分类为create或update。更新不同于补丁;补丁的HTTP动词是补丁。
2在“如果失败会发生什么”方面,我认为代码取决于出错的地方:
我不确定404是不是最好的代码,因为它没有告诉用户任何原因。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2023 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号: 粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
扫码关注腾讯云开发者
领取腾讯云代金券