使用具有不完整表示的 PUT 方法 [英] Using the PUT method with incomplete representations

查看:20
本文介绍了使用具有不完整表示的 PUT 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于资源的不完整表示的 PUT 预期的标准行为是什么?

What is the standard behavior expected from a PUT with an incomplete representation of the resource?

例如,我在 /api/users/1 中有一个 User,由下面的 HAL json 表示:

For instance, I have a User at the /api/users/1 that's represented by the HAL json below:

{'id': 1,
 'username': 'joedoe',
 'email': 'joe@doe.com',
 'password_hash': '9039dmk38f84uf4029i339kf32f0932i',
 'last_visit': '2013-11-04 21:09:01',
 'public': true,
 '_links': {'self': {'href': 'http://foo.bar.com/api/users/1'}}

}

然后,我发出一个 PUT 请求来更改 usernameemail,其中表示缺少其他属性:

Then, I make a PUT request to change username and email, with a representation missing the other attributes:

PUT /api/users/1

{'username': 'joeydoey',
 'email': 'joey@doey.com'}

到目前为止,我一直认为这应该被视为错误,因为它意味着部分更新,但是 这个答案 让我想到它,说不完整的表示仍然是一个完整的替代品是有道理的,它让服务器可以自由地用默认值填充空白.

Up till now, I always assumed this should be treated as an error, because it implies a partial update, but this answer got me thinking about it, and it makes sense to say that an incomplete representation is still a complete replacement that's giving the server liberty to fill in the blanks with defaults.

我在 HTTP 标准中找不到与此相关的任何内容,所以我不得不问,在这种情况下预期的标准化行为是什么?

I can't find anything that I could relate to this on the HTTP standard, so I have to ask, what's the standardized behavior expected in this case?

  1. 它应该会导致错误,因为它意味着部分更新.PUT 负载的架构应该与使用 GET 检索到的相同资源和媒体类型的架构相同.

  1. It should result in an error, because it implies a partial update. The schema of the PUT payload should be identical to the one retrieved with a GET to the same resource and media type.

它应该会成功,因为服务器可以自由地使用该媒体类型的默认值填充空白.在这种情况下,它会将密码重置为空白或默认密码并相应地刷新哈希,并将 last_visit 和 public 值设置为默认值.当您考虑 HATEOAS 时,此选项更有意义,如果客户端提交的媒体类型与服务器返回的相同,因为它无法预测超媒体控件将如何变化,因此每次客户端不完整时,表示肯定是不完整的'不发送所有超链接,服务器必须相应地重置它们.

It should succeed, because the server is free to fill the blanks with the defaults for that media type. In this case, it would reset the password to a blank or default password and refresh the hash accordingly, and set the last_visit and public values to defaults. This option makes a lot more sense when you consider HATEOAS, if the client is submitting the same media-type returned by the server, since it can't predict how the hypermedia controls will change, the representation is necessarily incomplete every time the client isn't sending all hyperlinks, and the server must reset them accordingly.

1 和 2 都是有效的,因为没有标准化的行为,由媒体类型决定如何处理它.这感觉不对,因为 PUT 并不从属于资源本身,而是替代它.

Both 1 and 2 are valid, because there's no standardized behavior and it's up to the media type to decide what to do with it. This doesn't feel right because a PUT is not subordinated to the resource itself, but rather replaces it.

请记住,我不是在问什么感觉正确或什么有意义.我问的是哪一个受标准支持.

Keep in mind that I'm not asking what feels right or what makes sense. I'm asking which one is backed by the standards.

推荐答案

只要 PUT 的结果是完全替代了客户端对资源的理解(即,那些未通过的属性的先前值不影响它们在 PUT 之后的值),它应该会成功.然而,它看起来确实有点令人困惑,因为很多人倾向于用字段级更新语义(而不是完全替换)来模糊这种 PUT 的使用.

As long as the result of the PUT is a complete replacement from the client's understanding of the resource (i.e., the previous values for those properties not passed do not influence their value after the PUT), it should succeed. However, it does make it a bit confusing to look at, since so many people have a tendency to equivocate this use of PUT with field-level update semantics (rather than complete replacement).

虽然从技术上讲这里没有违反 REST 约束,但传递所有值而不是求助于服务器默认值可能是一个更好的主意,因为这将有助于保持向前兼容性.默认值会随着时间而改变,因此通常应避免使用它们.

While there's technically no violation of REST constraints here, it's probably a better idea to pass in all values and not resort to server defaults, because that will help preserve forward compatibility. Defaults can change over time, so generally they should be avoided.

然而,您的链接示例并不是指不传递默认值,因此它不是不完整表示"的好例子.相反,链接不是客户端向服务器表示的资源的一部分.我认为您在这里引入了另一个概念:从服务器返回到客户端的属性.这就是我在引发这篇文章的另一个线程上谈论的内容.

Your example of links, however, is not referring to not passing defaults, so it's not a good example of an "incomplete representation." Rather, links aren't part of the client's representation of the resource to the server. I think you're bringing another concept into the mix here: properties which are only returned from the server to the client. This is what I was talking about on the other thread which sparked this post.

我所说的不是不完整的表示;这是一种不同的表现形式.您实际上是在处理描述相同资源的两种不同媒体类型(即表示).一个源自客户端(我们称之为 application/vnd.example.api.client),另一个源自服务器(application/vnd.example.api.server).它们可能没有被明确地标记为这样,但这至少是隐含正在发生的事情.因此,由于它们是两种不同的媒体类型,它们对相同资源表达了不同的内容.

What I am talking about is not an incomplete representation; it's a different representation. You are really dealing with two different media types (i.e., representations) describing the same resource. One originates from the client (we'll call it application/vnd.example.api.client), and the other originates from the server (application/vnd.example.api.server). They may not explicitly be labeled as such, but that's at least implicitly what's happening. Therefore, since they are two different media types, they express different things about the same resource.

既然您提到了 HAL,请考虑到客户端通常不会将媒体类型为 application/hal+json 的消息 POST 到服务器.以来自HALTalk的注册rel为例.预期的内容类型是 application/json,而不是 application/hal+json.而且,如果您查看示例帖子,就会发现它没有任何 HAL 风格.没有链接,没有嵌入的对象等.但是......如果你从这个 POST 返回的 Location 头中获取 URL,它会假设你的客户端接受 HAL over JSON,返回类型为 application/hal+json 的响应(即,有链接的用户).两种不同的媒体类型,同一资源的两种不同表现形式.

Since you mentioned HAL, consider that a client doesn't usually POST a message of media type application/hal+json to the server. Take a look at the signup rel from HALTalk for an example. The expected content type is application/json, not application/hal+json. And, if you look at the example post, there is nothing HAL-ish about it. No links, no embedded objects, etc. But... if you then GET the URL returned from the Location header returned from this POST, it will, assuming your client accepts HAL over JSON, return a response of type application/hal+json (i.e., a user with links). Two different media types, two different representations of the same resource.

所以让我用 Accept 和 Content-Type 标头装饰您的示例以说明我的观点.

So let me decorate your example with Accept and Content-Type headers to illustrate my point.

请求

PUT /api/users/1 HTTP/1.1
Content-Type: application/vnd.example.api.client+json

{'username': 'joeydoey',
 'email': 'joey@doey.com'}

回复

200 OK
Content-Type: application/hal+json;profile=application/vnd.example.api.server

{'id': 1,
 'username': 'joeydoey',
 'email': 'joey@doey.com',
 'password_hash': '9039dmk38f84uf4029i339kf32f0932i',
 '_links': {'self': {'href': 'http://foo.bar.com/api/users/1'}}
}

大多数系统不会详细描述它们的媒体类型.通常它只是以更通用的类型(如应用程序/json 或仅一种自定义媒体类型)构成框架.然而,这一切都没有改变这样一个事实,即虽然它是相同的底层资源,但它们是两种不同的表示形式.有道理吗?

Most systems don't go to this amount of detail to describe their media types. Usually it's just framed in a more generic type (like application/json or only one custom media type). However, none of this changes that fact that while it is the same underlying resource, these are two different representations. Make sense?

这篇关于使用具有不完整表示的 PUT 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆