ChatGPT解决这个技术问题 Extra ChatGPT

安静的 POST 响应的“最佳”实践

所以这里没有什么新东西我只是想得到一些澄清,似乎在其他帖子中找不到任何东西。

我正在重新创建一个新资源,比如说:

/books (POST)

有身体:

{
  title: 'The Lion, the Witch and the Wardrobe',
  author: 'C. S. Lewis'
}

我知道我应该返回一个 201(已创建),并带有新资源的 Location 标头:

Location: /books/12345

我似乎无法为自己回答的问题是服务器应该在正文中返回什么。

我经常做这样的回应:

{
  id: 12345,
  title: 'The Lion, the Witch and the Wardrobe',
  author: 'C. S. Lewis'
}

我这样做有几个原因:

我已经为 angularjs 等前端框架编写了 api。在我的特殊情况下,我使用的是角度资源,我经常只需要资源的 id 来定位它。如果我没有在响应正文中返回 id,我需要将其从 Location 标头中解析出来。在所有书籍的 GET 中,我通常会返回整个对象,而不仅仅是 id。从这个意义上说,我的客户端代码不必区分从哪里获取 id(位置标头或正文)。

现在我知道我真的处于灰色地带,但大多数人都说归还整个资源是“不好的”做法。但是,如果服务器更改/向资源添加信息怎么办。它肯定会添加 id,但也可能会添加其他内容,例如时间戳。在我不返回整个资源的情况下,执行 POST,返回 id,然后让客户端执行 GET 以获取新资源是否真的更好。

我个人更喜欢 POST 响应的空正文。 RESTful Location 标头值不应该是 URI(唯一资源标识符)吗?因此,也许您应该将其用作 ID 而不是解析它以找出服务器内部 ID。 IMO,RESTful API 消费者应该使用提供的超链接而不是构建路径进行导航,猜测特定服务器定位资源的位置......毕竟,客户端不知道它刚刚创建的资源的状态吗?重复它会浪费网络资源。
对于创建/插入,状态 201 - 已创建,标题位置 →localhost:8080/employees/1(请参阅:here

g
grahamesd

返回新对象符合“统一接口 - 通过表示操作资源”的 REST 原则。完整的对象是所创建对象的新状态的表示。

API 设计有一个非常好的参考,在这里:Best Practices for Designing a Pragmatic RESTful API

它在此处包含对您问题的回答:Updates & creation should return a resource representation

它说:

为防止 API 使用者不得不再次访问 API 以获取更新的表示,请让 API 返回更新(或创建)的表示作为响应的一部分。

对我来说似乎很实用,它符合我上面提到的 REST 原则。


返回整个相关对象集怎么样?这样,可能的排序可以在服务器端完成,它简化了前端的实现
但这些最佳实践并不是最好的。作者指出,与其他原则一样重要的 HATEOAS 一定不能使用,因为“它还没有准备好”。 HATEOAS 永远不会“准备好”,因为所有 RESTful 原则都只是架构设计原则,而不是具体实现。引用的参考资料是关于作者对 RESTful API 的看法,由于放弃了 HATEOAS,它根本不是 RESTful。这就是为什么这不是最好的参考:)
@marcinn - 你会注意到原来的问题在“最佳”周围有引号,我猜是因为在这个领域有很多意见。我指出的参考资料是我发现实用的。如果您有更好的参考,请分享。我总是乐于学习更多。
@grahamesd 实现与架构设计原则/模式不同。没有人可以期望 HATEOAS 有一天会准备好,但是有可能有人会创建一个被许多人接受的实现。 Vinay 还写了关于将 http 方法映射到 URL 和特定操作 (CRUD) 的文章,指出通过为 url 添加前缀的版本控制更加实用,并写道通过查询参数进行过滤是一种可行的方法……很好,但这一切都没有什么可做的使用 RESTful 架构。他写了一些合同。这对 HTTP API 来说很好,但不要称它为 RESTful。
@grahamesd 以下是一些解释这一点的帖子:- medium.com/@andrea.chiarelli/… - restfulapi.net
D
Daniel Perez

在更新时返回整个对象似乎不太相关,但我几乎不明白为什么在创建时返回整个对象在正常用例中是一种不好的做法。这至少对于轻松获取 ID 并在相关时获取时间戳很有用。这实际上是使用 Rails 搭建脚手架时的默认行为。

我真的看不出只返回 ID 并在之后执行 GET 请求以获取您可以通过初始 POST 获得的数据的任何优势。

无论如何,只要您的 API 是一致的,我认为您应该选择最适合您需求的模式。没有任何正确的方法来构建 REST API,imo。


我知道这是旧的,但我可以给出一个令人信服的论点,在你的 POST 之后使用 GET。在 http/1.1 规范中,任何历史工具都可以忽略从您的 GET 响应传回的缓存设置...因此,如果您的用户在使用 POST 更新后使用浏览器中的后退按钮返回此页面,则它可以使用陈旧的来自原始 GET 的缓存数据。因此,如果您重用 GET,那么您可以更新缓存并更好地了解页面离开时的外观......
@Shaded 如果 API 也被设计为供应用程序使用,那么您提出两个请求的论点不成立。在那里,您通常通过将模型类型的对象保存在内存中来缓存数据——这通常是通过 POST 请求的响应来完成的。关于浏览器,只要还有一个 GET api 端点,对 POST 请求的响应就不会真正受到伤害。
我同意丹尼尔在这里所说的。即使你检查像 Spring Data 这样的成熟框架,它们总是在持久化后返回整个对象。我认为这是一个很好的做法,因为在您的客户端中,您将保存服务器往返以获取相同的信息
S
Somaiah Kumbera

发完帖子后,我喜欢返回如下内容:

Response
   .created(URI("/obj/$id"))
   .entity(TheNewObj())
   .build()

状态 201 - 已创建

Header Location - 新对象的位置

实体 - 新对象