GET和PUT的表示相同吗?

时间:2016-04-08 11:57:59

标签: rest http

正如其他人(例如:here)我在努力解决这个问题时,GETPUT的代表应该相同吗?

示例:

GET表示:

{
    "id": "0815",
    "name": "jdoe",
    "emailAddress": "jd@example.com",
    "displayName": "John Doe",
    "active": true
}

PUT表示:

{
    "emailAddress": "jd@example.com",
    "displayName": "John Doe"
}

研究

我在REST question: PUT one representation, GET a different one?中读到,当我用PUT保存时,可以使用GET获得另一种媒体类型。

我在REST - put IDs in body or not?中读到,可以通过PUT省略id并使用GET获取id。

我在GET Representation != POST Representation中读到,可以通过PUT省略很多属性并使用GET获取它们。一个例子是JIRA REST API - api/2/myself。 GET返回空洞用户模型,PUT只保存3个属性。

这是好习惯吗?我也可以使用PATCH,例如GitHub REST API - users。如果PUT具有另一个较小的表示已足够,那么将PATCH添加到HTTP的原因是什么?

我在Best practice for partial updates in a RESTful service中读到的更多大REST API(例如:Google)使用PATCH或POST进行部分更新,而PUT仅用于完整/完整更新(例如: :Goolge - Updating an entity)。

2 个答案:

答案 0 :(得分:4)

这个想法是服务器通常比用户有更多关于资源的信息,因此GET 可能返回的信息多于PUT所需的信息。服务器'拥有'有一些东西,因此客户端无法更新。这些可以由GET返回,而PUT表示不允许用户修改它们。

然而,这与PUT允许您部分更新资源的说法不同。当您输入文档时,您将更新该文档所涵盖的所有值 - 因此,应通过PUT发送的实际文档中不存在的“可选”值将从资源中删除<​​/ em>。当您对该资源执行后续GET时,将不会显示可选值。

PATCH的语义应该略有不同 - 使用PATCH,客户端发送部分更新,以某种方式描述更改。然后,这些更改以某种方式应用于资源。通过PATCH发送的文档中未提及的资源部分将不加修改。

另请注意,PATCH明确定义为既不安全也不是幂等。虽然PUT是幂等的但不安全 - 重复的相同请求将导致相同的变化。使用PATCH,某些更改可能是累积的(例如,向列表添加值),因此重复的请求可能会导致资源的状态不同。

答案 1 :(得分:1)

我在努力解决这个完全相同的问题。感谢您对它的研究以及对它的清晰表达。我认为这里存在的问题是,服务器/后端确定/创建了 的数据,REST尚未真正解决最佳实践问题。例如:

  • GUID&#39; S
  • 独特/顺序ID
  • 时间戳

在每个简单的REST示例中,您看到它与您的POST / PUT之间的内容之间似乎相当对称。例如,REST会让你相信,如果你对集合(或资源)进行GET,然后POST(或PUT)那个响应主体就应该没有变化,但这只是不现实的考虑上述例子。所以从本质上讲,你的GET响应成为实际POST / PUT主体的超集。

我用这个术语作为对两者之间关系不对称的头部点头,就是说我的GET返回集合/资源的Readonly表示,而不是POST / PUT主体接受的。这很适合代码,您可以从对象继承Readonly表示,以使用您的服务器/后端负责创建/管理的属性来扩充它。例如,这里有两个TypeScript接口,显示用户可以PUT(IPet)的数据与服务器为GET(IReadonlyPet)响应的数据

interface IPet {
    name: string, // The user can change the pet's name
}
interface IReadonlyPet extends IPet {
    id: number,  // The user should not be able to change the pet's id
}

我不知道我是否强迫用户在GET请求之后进行POST / PUT时剥离id之类的内容,因为这需要很多数据转换努力询问您的API消费者。我可以看到两个有效且相反的论点:

  • 允许他们使用数据创建/更新的边缘线不良做法,您只接受某些属性,但默默地忽略其他属性(即他们可以使用与他们收到的不同id并且你只是默默地忽略它可能会让他们错误地了解集合/资源的实际状态。
  • 格言&#34;对你所接受的内容持开放态度,严格对待你所生成的内容&#34; 将规定对于你所定义的模式而言多余的属性可以安全地忽略为客户端生成任何错误。所以有人可以进行GET,然后修改id,然后执行POST / PUT,你就会忽略id属性。

如果我必须选择一个,我可能会选择第二个选项,因为我认为它可以为您的API消费者提供更简单,更对称的体验,因为他们可以完成一个完整的GET,POST / PUT GET响应,并再次获得GET以获得相同的原始响应。此外,您的API使用者可能真的抱怨超出定义架构的数据的实现行为,因为您已经脱离了标准化的常规路径。