简体   繁体   English

REST API:是否应该使用PUT或DELETE来部分更新资源?

[英]REST API: Should we use PUT or DELETE to update resource partially?

We have website like pluralsight where authors and customers register. 我们有一个网站像多元化,作者和客户都在这里注册。 Authors publish their courses and customers can give rating to these courses. 作者发布他们的课程,客户可以对这些课程进行评分。 The table structure looks like: 表结构如下:

author table: (save basic information of author: one to one) 作者表:(保存作者的基本信息:一对一)

authorId | authorId | name | 名称| contact | 联系| email | 电邮| rating 评分

1 | 1 | sahil | 萨希尔| 9971343992 | 9971343992 | shaf@gmail.com | shaf@gmail.com | 3.2 3.2

authorRating: (save ratings given to author from customers: one to many) authorRating :(保存给客户的作者评级:一对多)

Id | ID | authorId | authorId | customerId | customerId | rating | 评级|

1 | 1 | 1 | 1 | 101 | 101 | 2.7 2.7

2 | 2 | 1 | 1 | 201 | 201 | 3.7 3.7

The rating in the author table gets updated when some record gets inserted/updated/deleted in authorRating table. 当在authorRating表中插入/更新/删除某些记录时,author表中的评级将更新。 There's some complex algorithm which finalize rating in author table based on authorRating table records. 有一些复杂的算法可以根据authorRating表记录最终确定author表中的评分。

We have created following APIs for that: 为此,我们创建了以下API:

PUT api/author/1/rating /: If there's any change in authorRating table, we recompute the rating of that author and trigger this API to pass new rating. PUT api / author / 1 / rating /:如果authorRating表中有任何更改,我们将重新计算该作者的评分,并触发此API传递新的评分。 This accepts rating and add/update that in author table. 这接受评分并在作者表中添加/更新。 If author table doesn't have id=1, it gives back validation error 如果作者表没有id = 1,则返回验证错误

DELETE api/author/1/rating /: This removes the rating for author id=1 ie set it to NULL. 删除api / author / 1 / rating /:删除作者ID = 1的评分,即将其设置为NULL。 If author table doesn't have id=1, it gives back validation error. 如果作者表没有id = 1,则会返回验证错误。

Is this the right API design? 这是正确的API设计吗? OR should we only have PUT API exposed and if they send rating as null in the PUT API, we will set it null in the author table ? 还是应该只公开PUT API,如果它们在PUT API中将等级发送为null,我们将在author表中将其设置为null?

OR should we consider using PATCH here? 还是我们应该考虑在这里使用PATCH?

至于您只修改一个结构的字段,我认为PATCH在这里更合适,但应将其发送到父资源:

PATCH api/author/1

For these rating operations, I would use something like: 对于这些评级操作,我将使用类似以下内容的方法:

  • To insert a new rating for author 1, use POST /api/author/1/rating 要为作者1插入新的评分,请使用POST /api/author/1/rating
  • To update a rating for author 1, use PATCH /api/author/1/rating . 要更新作者1的评分,请使用PATCH /api/author/1/rating You may want to have more data in the authorRating table that don't want to change (like author and customer ids) but you are only updating some fields, in this case, the rating. 您可能希望authorRating表中有更多不想更改的数据(例如作者和客户ID),但您只更新了某些字段,在这种情况下是等级。
  • To delete author's 1 rating, DELETE /api/author/1/rating , as you explained, makes sense. 如您所解释的,要删除作者的1级, DELETE /api/author/1/rating是有意义的。

It is a common practice to use POST method for RESTful APIs. 对RESTful API使用POST方法是一种常见的做法。 You can post virtually any message and handle the message by the parameters. 您几乎可以张贴任何消息,并可以通过参数处理该消息。 You can POST a delete, or update or other command, depending on your needs. 您可以根据需要发布删除,更新或其他命令。

HTTP is a protocol which defines methods that allow to manipulate resources; HTTP是一种协议,它定义了允许操作资源的方法。 files or data on the internet so to say. 可以这么说。 Any business logic triggered by one of the operations invoked are more or less just side effects while manipulating these resources. 在操纵这些资源时,由调用的操作之一触发的任何业务逻辑或多或少只是副作用。 While certain things can be achived in multiple ways, operations (slightly) differ in their semantics they convey. 尽管某些事情可以通过多种方式实现,但操作(在语义上)略有不同。

PUT as specified in RFC 7231 , which replaces the current representation with the one provided in the request, does state the following about partial updates: RFC 7231中指定的PUT将当前表示替换为请求中提供的表示,它声明了有关部分更新的以下内容:

Partial content updates are possible by targeting a separately identified resource with state that overlaps a portion of the larger resource , or by using a different method that has been specifically defined for partial updates (for example, the PATCH method defined in RFC5789 ). 通过以状态与较大资源的一部分重叠的状态单独标识资源目标 ,或者通过使用专门为部分更新定义的其他方法 (例如, RFC5789中定义的PATCH方法),可以进行部分内容更新。

So, you have either the option of "overlapping" resources and update the other resource, which has the effect of also changing the overlapping data and thus the data in the actual resource as well, or use PATCH therefore. 因此,您可以选择“重叠”资源并更新另一个资源,这样的效果还可以更改重叠数据,从而也可以更改实际资源中的数据,或者使用PATCH

The primer one can easily be thought of that certain information of an other resource is embedded in the actual resource and on updating the other resource the state of the actual resource will also change as a consequence. 入门者很容易想到另一资源的某些信息被嵌入到实际资源中,并且在更新另一资源时,实际资源的状态也将因此而改变。 Think of a user and his address ie 想一想用户及其地址,即

According to Roy Fielding, who wrote the following in his dissertation 根据罗伊·菲尔丁(Roy Fielding)的论文,他在论文中写道:

The key abstraction of information in REST is a resource. REST中信息的关键抽象是一种资源。 Any information that can be named can be a resource : a document or image, a temporal service (eg "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (eg a person), and so on. 可以命名的任何信息都可以是资源 :文档或图像,临时服务(例如“洛杉矶今天的天气”),其他资源的集合,非虚拟对象(例如人)等。 In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. 换句话说,任何可能成为作者超文本引用目标的概念都必须符合资源的定义。 A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time .” 资源是到一组实体的概念性映射,而不是在任何特定时间点对应于该映射的实体 。”

resources should be named and referenced via own, unique identifiers. 资源应通过自己的唯一标识符来命名和引用。 A direct mapping of entities to resources though is often not desirable as the resource can and probably should contain more information for the client to take further actions. 尽管通常不希望将实体直接映射到资源,因为资源可以并且可能应该包含更多信息,以便客户端采取进一步的措施。

It is therefore up to you if you consider a rating to be a good entity and/or a good resource. 因此,取决于您是否将评级视为一个好的实体和/或一个好的资源。 I'm not a big fan of this though, though this is an opinionated position. 尽管这是一个自以为是的立场,但我不是这个的忠实拥护者。

DELETE has some special semantics. DELETE具有一些特殊的语义。 It actually does not guarantee the removal of a file, though it will make the resource unavailable by removing the association (the URI) for that particular resource. 尽管通过删除特定资源的关联(URI)将使资源不可用,但它实际上不能保证删除文件。 What happens to the deleted resource is actually up to the implementation. 实际上,删除的资源将取决于实现。

The DELETE method requests that the origin server remove the association between the target resource and its current functionality . DELETE方法请求源服务器删除目标资源与其当前功能之间的关联 In effect, this method is similar to the rm command in UNIX: it expresses a deletion operation on the URI mapping of the origin server rather than an expectation that the previously associated information be deleted. 实际上,此方法类似于UNIX中的rm命令:它在源服务器的URI映射上表示删除操作,而不是期望删除先前关联的信息。

... ...

If the target resource has one or more current representations, they might or might not be destroyed by the origin server, and the associated storage might or might not be reclaimed, depending entirely on the nature of the resource and its implementation by the origin server (which are beyond the scope of this specification). 如果目标资源具有一个或多个当前表示,则它们可能会或可能不会被原始服务器销毁,并且相关的存储可能会或可能不会被回收,这完全取决于资源的性质及其由原始服务器的实现(超出了本规范的范围)。 ... In general, it is assumed that the origin server will only allow DELETE on resources for which it has a prescribed mechanism for accomplishing the deletion. ...通常,假定原始服务器仅对具有预定机制以完成删除的资源允许DELETE。

Usually DELETE should only be used on resources that where created via PUT or POST previously whose creation was confirmed via an own Location response header. 通常, DELETE仅应用于先前通过PUTPOST创建且已通过自己的Location响应标头确认创建的资源。

With that being said, as you aked for whether this is the right API design or not. 话虽如此,您一直在寻求这是否是正确的API设计。 Actually, there is no right or wrong and which stance you take is primarily an opinionated one. 实际上,没有对与错,您所采取的立场主要是自以为是。 As long as you stay in bounds with the HTTP protocol specification (in your particular case) you don't violate REST architect principles. 只要您遵守HTTP协议规范(在您的特定情况下),您就不会违反REST架构师原则。 If you design your rating resources in a way that make them uniquely identifiable you can use delete to unreference the respective rating from the author (and probably delete the data from your DB) or send a put request with the new content of that rating resource to the respective endpoint. 如果您以一种可唯一识别的方式设计评分资源,则可以使用Delete取消引用作者的相应评分(并可能从数据库中删除数据),或将包含该评分资源的新内容的放置请求发送到各自的端点。

Keep in mind though, that the server should do its best to teach the client what next actions it can take without having the client to have some out-of-band information about your API, otherwise you will couple the client to your API and therefore might cause problems when you change your API in the future. 不过请记住,服务器应尽最大努力告诉客户端它可以采取的下一步操作,而不必让客户端获得有关您的API的一些带外信息,否则,您会将客户端与API耦合,因此将来更改API时可能会引起问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM