使用带有不完整表示的PUT方法
PUT预期的标准行为是什么,并且资源不完整?
例如,我在/api/users/1
上有一个User
,由下面的HAL json表示:
{'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请求来更改username
和email
,其中一个表示缺少其他属性:
PUT /api/users/1
{'username': 'joeydoey',
'email': 'joey@doey.com'}
到目前为止,我一直认为这应该被看作是一个错误,因为它意味着一个部分更新,但是这个答案让我想到了它,并且说一个不完整的表示仍然是一个完整的替代方案,它给了服务器自由填补缺席的空白。
我无法在HTTP标准中找到任何与此相关的内容,所以我必须问,在这种情况下,预期的标准化行为是什么?
它应该会导致错误,因为它意味着部分更新。 PUT有效载荷的模式应该与使用GET检索相同资源和媒体类型的模式相同。
它应该是成功的,因为服务器可以自由地填充空白以及该媒体类型的默认值。 在这种情况下,它会将密码重置为空白或默认密码并相应地刷新哈希值,并将last_visit和public值设置为默认值。 当您考虑HATEOAS时,如果客户端提交服务器返回的相同媒体类型,此选项会更有意义,因为它无法预测超媒体控件如何更改,每次客户端不是每次都是不完整的不发送所有超链接,并且服务器必须相应地重置它们。
1和2都是有效的,因为没有标准化的行为,并且由媒体类型决定如何处理它。 这并不正确,因为PUT不是从属于资源本身,而是取而代之。
请记住,我不是在问什么是对的或什么是有道理的。 我在问哪一个标准支持。
只要PUT的结果是从客户对资源的理解中完全替代(即,未通过的那些属性的先前值不会影响它们在PUT后的值),它应该成功。 然而,它看起来有点令人困惑,因为许多人倾向于将PUT的这种使用与场级更新语义(而不是完全替代)等同起来。
虽然在技术上没有违反REST约束的情况,但传递所有值并不诉诸服务器默认值可能更好,因为这有助于保持向前兼容性。 默认值可以随时间变化,所以一般应该避免。
然而,你的链接的例子并不是指不传递默认值,所以它不是一个“不完全表示”的好例子。 相反,链接不是客户端对服务器资源表示的一部分。 我想你会在这里混合使用另一个概念:只从服务器返回给客户端的属性。 这就是我在引发这篇文章的另一篇文章中谈到的。
我所说的并不是不完整的表述; 这是一种不同的表现形式。 你真的在处理描述相同资源的两种不同媒体类型(即表示)。 一个来自客户端(我们将其称为application / vnd.example.api.client),另一个来自服务器(application / vnd.example.api.server)。 它们可能没有被明确标记,但至少隐含地发生了什么。 因此,由于它们是两种不同的媒体类型,它们表达关于同一资源的不同事物。
既然你提到了HAL,考虑到客户端通常不会向服务器发送媒体类型application / hal + json的消息。 以HALTalk的rel注册为例。 预期的内容类型是application / json,而不是application / hal + json。 而且,如果你看一下示例文章,这里没有关于它的内容。 没有链接,没有嵌入对象等等。但是......如果你从这个POST返回的Location头返回的URL,假设你的客户端接受HAL通过JSON,返回一个类型为application / hal + json的响应(即,具有链接的用户)。 两种不同的媒体类型,相同资源的两种不同表示。
因此,让我用Accept和Content-Type标题来修饰您的示例以说明我的观点。
请求
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或只有一个自定义媒体类型)。 然而,这些都没有改变这一事实,尽管它是相同的基础资源,但这是两种不同的表示。 合理?
PUT用于替换。 服务器可以修改/增加数据,但最终表示应该是有效负载的函数,而不是最终状态的函数。
在你的例子中,密码哈希似乎不是服务器可以填写的东西,对吧? 在这种情况下,PUT应该导致错误。
链接地址: http://www.djcxy.com/p/71259.html上一篇: Using the PUT method with incomplete representations
下一篇: what are REST,RESTFul, SOA and microservices in simple terms?