VansFannel
VansFannel

Reputation: 45921

Update a RESTFul resource adding an element or deleting an element from its set, are both PUT operations?

I have a RESTFul API with a resource that represent a set reference by a key.

I have an operation to add an element to the set as PUT and its URI is api/Aggregation/{key}.

The operation to destroy the set is DELETE and its URI is api/Aggregation/{key}.

But if I want to remove an element from the set, which verb do I have to use it?

I have thought to use PUT operation and add a value inside the body to indicate if I'm deleting or adding an element to the set but I don't know if it is a best practices for Restful design.

Upvotes: 3

Views: 1487

Answers (2)

milan.latinovic
milan.latinovic

Reputation: 2407

I would approach this issue by deciding between PUT and PATCH verbs (instead of PUT and DELETE). Let's consult a PUT and PATCH definitions, according to RFC 2616.

PUT is defined in Section 9.6 RFC 2616:

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

PATCH is defined in RFC 5789:

The PATCH method requests that a set of changes described in the requesting entity be applied to the resource identified by the Request- URI.

Having that in mind, I believe that the right approach to removing one element from already existing set would be a PATCH verb. For example, if your endpoint creates a whole new set, you will use POST, if it deletes it you will use DELETE, but if it changes it in any way (adds new items or deletes a specific item, BUT without removing/adding of the whole parent) it should be PATCH.

Now, there is the 2nd side of this coin... :)

You might have multiple endpoints to handle this, and some endpoints might look at a single set as a parent. In that case, POST/DELETE is the right approach.

To summarize, let's look at a couple of endpoints...

POST       /myGreatApi/v1/set/create
DELETE     /myGreatApi/v1/set/delete
PATCH      /myGreatApi/v1/set/addElement
PATCH      /myGreatApi/v1/set/removeElement

On the other hand, if you have different API structure...

POST      /myGreatApi/v1/set/create
DELETE    /myGreatApi/v1/set/delete
POST      /myGreatApi/v1/set/{id}/element/create
DELETE    /myGreatApi/v1/set/{id}/element/delete
POST      /myGreatApi/v1/element/{id}/addToSet/{id}
DELETE    /myGreatApi/v1/element/{id}/removeFromSet/{id}

Having all this in mind, I don't think there is a 'best practices approach' as is. Your HTTP verbs depend on the actual API structure that you decide to implement.

Bottom line, if you document it well enough for your users to be able to use it, then you did a good job... :) As far as good practices are concerned, I would always think about it this way: "Am I creating/removing whole parent element, or am I changing (adding, deleting) a child elements inside that parent? Is my API correctly representing this action?"

Hope that you'll find this helpful.

Note: As @Evert commented below, using HTTP verbs inside API structure is not considered a good practice. The example above holds HTTP verbs to point correct action that is about to be taken.

Kind regards,

Upvotes: 0

Evert
Evert

Reputation: 99571

If this uri represents your set:

/api/Aggregation/{key}.

Then doing a PUT request on it does not add anything to the set, it completely replaces the set.

What you probably want, is have individual items in the set represented by another resource, such as:

/api/Aggregation/{key}/{item}

Then you can do a PUT request to create/replace items in the set, and DELETE to remove items from the set.

Alternatively, you could use POST to append a new item to the set. This request would happen usually on the set url though:

POST /api/Aggregation/{key}

This is a really common pattern:

GET    /api/Aggregation/{key}        - to get the entire set.
DELETE /api/Aggregation/{key}        - to delete the entire set.
PUT    /api/Aggregation/{key}        - to replace the set
POST   /api/Aggregation/{key}        - to add something to the set
GET    /api/Aggregation/{key}/{item} - to retrieve a single item
PUT    /api/Aggregation/{key}/{item} - to update an item (or create an item by name)
DELETE /api/Aggregation/{key}/{item} - to delete an item

This is probably the most 'RESTful' approach. If you don't like creating individual resources for items in the set, you might need to do something that's arguable not as RESTful, such as PATCH on a collection, which is more RPC-like than REST-like.

tl;dr: PUT always completely replaces the resource at the target URI.

Upvotes: 4

Related Questions