How to design a RESTful collection resource? - rest

I am trying to design a "collection of items" resource. I need to support the following operations:
Create the collection
Remove the collection
Add a single item to the collection
Add multiple items to the collection
Remove a single item from the collection
Remove multiple items from the collection
This is as far as I have gone:
Create collection:
==>
POST /service
Host: www.myserver.com
Content-Type: application/xml
<collection name="items">
<item href="item1"/>
<item href="item2"/>
<item href="item3"/>
</collection>
<==
201 Created
Location: http://myserver.com/service/items
Content-Type: application/xml
...
Remove collection:
==>
DELETE /service/items
<==
200 OK
Removing a single item from the collection:
==>
DELETE /service/items/item1
<==
200 OK
However, I am finding supporting the other operations a bit tricky i.e. what methods can I use to:
Add single or multiple items to the collection. (PUT doesn't seem to be right here as per HTTP 1.1 RFC
Remove multiple items from the collection in one transaction. (DELETE doesn't seem to right here either)

You would be better off using a non-positional identifier such as a UUID for collection items, to avoid problems such as the url of an item changing when you delete an item that precedes it. (Of course, you can still use itemN or just N, as long as the number stays attached to the same item at all times, leaving gaps after deletions, but a UUID is less confusing.)
The collection has the url /service/items/. Each item has the url /service/items/<id>.
Creating items and collections is a POST on the parent of the resource.
You could use a PUT if the client has the right and ability to generate the name or id of the resource.
Removing items and collections is a DELETE on the resource itself.
Adding multiple items is either multiple POST or a multi-item POST on the parent (the collection).
Removing multiple items is a DELETE on each resource. I would discourage multi-item DELETE for two reasons:
Bulk deletion is a dangerous operation (for which reason, I would also discourage DELETE on a non-empty collection).
The only meaningful target of the operation is the parent collection, thus making bulk DELETE asymmetric with respect to single-item DELETE.
If you really need bulk deletion capability, provide it through a different, clearly marked API, such as PURGE /service/items.

to add items to the collection, you POST them to the collection's URL (http://myserver.com/service/items). in your case, you already have a 'multiple items' representation in XML, just POST that.
I don't know a simple way to remove multiple items on a single operation... may you could PUT to the collection's item with a list of id's to retain. the idea being that PUT updates the container, so what's not there is removed. and, i think it's not useful to provide the whole data you want to keep, just the references of the items.

What's wrong with PUT to create an element? You cited the HTTP RFC, but the HTTP RFC doesn't preclude the use of PUT to create an element in your collection, as far as I know. If I've missed something, please make a specific citation, with an excerpt.
The key difference between PUT and POST to create elements:
PUT should be an idempotent operation; POST is not.
For deleting multiple elements in a single transaction, you can send DELETE to a URL that specifies a range (/service/items/13-20, or you can send DELETE to /service/items and use the HTTP Range header (See RFC2616 sec. 14.35.2). Normally the range header is contrued to imply a byte range, and is used on a GET request, but it's up to your resource to infer the meaning of RANGE on a DELETE.

Why not use the AtomPub spec and adhere to the decisions written there? This way new clients could easily consume your data (using GData libraries..simple) and things like paged data feeds and the symantics of GET/POST/PUT/DELETE are solidly defined. Just my $.02.

Use Content-Type /text/uri-list and manage with PUT,GET,PATCH,DELETE a list
of links to the resources you want to collect.
The PATCH format you need could be very simple: just prefix with "+ " or "- " the modality of the change each uri bring to the collection.
Unfortunately, this media type, which could be named text/uri-list-update, is not yet officially registered, to my knowledge.

Related

Good REST API design for operations on resource sets

With REST it is pretty clear how to operate on resources, e.g.
PUT /users/{userId} - updates the user with userId
GET /users/{userId} - reads the user with userId
Similarly for resource sets
POST /users - creates a new user
GET /users/{userId}/books - reads list of books from a user
GET /users/{userId}/books?filter=x - reads list of books from a user with specific filter
What if I want to develop more elaborate operations on resource sets, e.g.
with the request body, add a list of books to the existing list and accepting duplicates (basically concatenating the list)
POST /users/{userId}/books
or PUT /users/{userId}/books
or PATCH?
or POST /users/{userId}/books/concatenate
with the request body, add a list of books to the existing list but no duplicates (basically merging the list)
POST /users/{userId}/books
or PUT /users/{userId}/books
or PATCH?
or POST /users/{userId}/books/merge
also for deleting parts of resource sets:
with the request body, delete a list of books from the existing list that have a certain property
POST /users/{userId}/books/delete?category=x
or DELETE /users/{userId}/books?category=x
or deleting all resources in a resource set:
POST /users/{userId}/books/delete_all
or DELETE /users/{userId}/books
Would be thankful for some hints or guidelines
"Resource sets", from the point of view of REST, are a fiction. There are only resources. As far as a general-purpose HTTP component is concerned, there is _no relation implied by the following URI:
/users
/users/{userId}
/users/{userId}/books
/users/{userId}/books?filter=x
/users/{userId}/books/concatenate
They are completely independent of one another; for instance, DELETE /users does not imply anything about the other resources.
We human beings tend to assign identifiers in patterns that make sense, but the machines don't care.
with the request body, add a list of books to the existing list and accepting duplicates (basically concatenating the list)
PUT and PATCH have remote authoring semantics; they act like you would expect if you were trying to edit a copy of a file on the server. You GET a copy of the current representation of the resource, make edits to your local copy, and then request that the server change its copy to match your copy. With PUT, you send a complete copy of your representation of the resource; with PATCH, you send a patch-document that describes the changes you made.
It's okay to use POST; HTML got along just fine using nothing but GET and POST, and the web took over the world.
You don't need a separate resource for POST; you can use one if you like, but it isn't necessary to do so.
with the request body, add a list of books to the existing list but no duplicates (basically merging the list)
Not really any different; what we agree upon in HTTP is the semantics of the request and response messages. What the server chooses to do is an implementation concern. See Fielding 2002.
So if I send to you a representation of a list with duplicate entries, and you strip out the duplicates, that's "fine"; you just need to exercise some care with your responses to ensure that you don't imply that you accepted the requested representation as is.
With PATCH, it's a bit fuzzy, in that the RFC describes all or nothing semantics, but based on the language used it is reasonable to infer that the implementation is restricted as well.
also for deleting parts of resource sets: with the request body, delete a list of books from the existing list that have a certain property
Give RFC 7231 a careful read: DELETE doesn't quite mean what your examples hint at. DELETE breaks the associate between a key (the target uri) and a value (the resource representations), but that doesn't necessarily mean "and also garbage collect the representation".
The same idea expressed another way -- suppose I GET /list-of-books from the server, and the returned representation is a list of three books. In the case where I want that resource to instead return a representation of an empty list, DELETE is the wrong tool. DELETE tells the server that I want future calls to GET /list-of-books to return 404 Not Found or possibly 410 Gone. If what I really want is a 200 OK with an empty list, then I need to PUT/PATCH/POST/etc. the resource.
deleting all resources in a resource set
Same problem as before.
With REST it is pretty clear how to operate on resources
This is the problem - it is NOT clear how to operate on resources. The web is cluttered with literature that makes a complete hash of it (we use REST to fetch documents that mangle the lessons of REST -- fabulous irony).
REST includes a uniform interface as a constraint. In HTTP, that interface is effectively a document store. PUT and PATCH just edit document contents - which is perfectly satisfactory if your domain is anemic or declarative. For anything else where we don't have standardized semantics, we use POST.
See Jim Webber, 2011: "You have to learn how to use HTTP to trigger business activity as a side effect of moving documents around the network."

REST best practice for updating an item in an array of items

In my single page application that uses RESTful services, I want to know what the best practice is for updating one item in an array of items.
Prerequisites
1. Front-end makes a GET request to fetch a list of items
2. Front-end formats the list of items (i.e. converts dates from UTC to local time)
3. Front-end makes a PUT request to the back-end to update the name of an item
Possible solutions
Solution #1
4. Back-end responds with HTTP-200 and the single updated item
5. Front-end reformats the updated item
6. Front-end splices the list of items, finding and replacing the updated item
PRO
- One API request to update the item
CON
- Duplication of data on the front-end, no single source of truth (i.e. the list of items)
Solution #2
4. Back-end responds with HTTP-200 and the updated list of items
5. Front-end reformats the list of items
PRO
- One API request to update the item
CON
- Does not follow the single responsibility principle (i.e. the API for updating the item updates the single item, and returns all items)
Solution #3
4. Back-end responds with HTTP-200 and the single updated item
5. Front-end makes a GET request to fetch all of the items
6. Front-end reformats the list of items
PRO
- More flexible for future implementations, APIs follow the single responsibility principle
CON
- Two API requests to update the item
I want to know what the best practice is for updating one item in an array of items.
An important thing to understand about REST, or HTTP, is that we are designing messages to be consumed by general-purpose components. Which is to say, we are using the readily standardized forms to communicate the semantics.
An HTTP PUT has the semantics of upserting a document into a document store. For your example, where we GET a representation of a list resource, make local edits, and PUT the result, the payload of the PUT is a copy of the complete representation of the resource -- what we are asking is that the server make it's copy look like the client's copy.
Assuming that the server elects to apply the new representation to its copy of the resource, the payload of the response could be a status message ("It worked"), or a copy of the new representation of the resource, or even an empty document (204 No Content) with metadata that describing the new representation of the resource (and the implication that the server accepted the client's representation without modification).
The key idea behind PUT, however, is that the payload is a complete representation of the resource, not merely a description of a change made to it. If the document is very large (in particular, large in comparison to the HTTP headers), and the edit you are making is small, then you may prefer to send a patch-document describing the changes you made to the document, specifying the PATCH method in the request.
Of course, on the web, the most popular document format didn't include hypermedia support for PUT or PATCH, and the most popular clients were browsers, not document editors, so we had to design our change protocols around POST. So it's "fine" to do it that way too, you just need to think about how representations of form data are going to be applied to the resource.
Solution 2 does follow the single responsibility principle, you might be confused by the naming and 'responsibility', but if we consider the true definition of SRP: 'single reason for change' Solution 2 is completely fine and the preferred way if performance is not critical.
https://deviq.com/single-responsibility-principle/

Correct URI for REST calls to create & delete relationship between two entities

I need to create and delete relationships between two different entities through REST calls.
Let's say user A (the current user) is going to follow or un-follow user B. The existence of a follow relationship is denoted by the presense or absence of the Follow relationship entity (Follow(B, A) means that A follows B).
Should the calls be:
POST /api/follow/{user-b-id} // to follow
and
DELETE /api/follow/{user-b-id} // to un-follow
where the identity of user A is deduced from the token sent along to authenticate the call.
Or should they be based on the action being carried out:
POST /api/follow/{user-b-id} // to follow
and
POST /api/unfollow/{user-b-id} // to un-follow
I have doubts about which methods (POST, PUT, DELETE etc.) to use and whether the URIs should reference the action (verb?) being carried out. Since I am re-designing an API, I want to get as close to "correct" (yes, I do realize that's a little subjective) REST API design as makes sense for my project.
Correct URI for REST calls to create & delete relationship between two entities
REST doesn't care what spelling you use for your URI; /182b2559-5772-40fd-af84-297e3a4b4bcb is a perfectly find URI as far as REST is concerned. The constraints on spelling don't come from REST, but instead whatever the local coding standard is.
A common standard is to consider a collection resource that includes items; such that adding an item resource to a collection is modeled by sending a message to the collection resource, and removing the item resource is modeled by sending a message to the item resource. The Atom Publishing Protocol, for instance, works this way - a POST to a collection resource adds a new entry, a DELETE to the item resource removes the entry.
Following this approach, the usual guideline would be that the collection resource is named for the collection, with the item resources subordinate to it.
// Follow
POST /api/relationships
// Unfollow
DELETE /api/relationships/{id}
id here might be user-b-id or it might be something else; one of the core ideas in REST is that the server is the authority for its URI space; the server may embed information into the URI, at it's own discretion and for its own exclusive use. Consumers are expected to treat the identifiers as opaque units.
I have doubts about which methods (POST, PUT, DELETE etc.) to use and whether the URIs should reference the action (verb?) being carried out.
It's sometimes helpful to keep in mind that the world wide web has been explosively successful even though the primary media type in use (HTML) supports only GET and POST natively.
Technically, you can use POST for everything. The HTTP uniform interface gives you carte blanche.
PUT, DELETE, PATCH can all be considered specializations of POST: unsafe methods with additional semantics. PUT suggests idempotent replace semantics, DELETE suggests remove, PATCH for an all or nothing update.
Referencing the action isn't wrong (REST doesn't care about spelling, remember), but it does suggest that you are thinking about the effects of the messages rather than about the resources that the messages are acting upon.
JSON Patch may be a useful example to keep in mind. The operations (add, remove, replace, and so on) are encoded into the patch document, the URI specifies which resource should be modified with those operations.
Jim Webber expressed the idea this way - HTTP is a document transfer application. Useful work is a side effect of exchanging documents. The URI identify the documents that are used to navigate your integration protocol.
So if you need consistent, human readable spellings for your URI, one way to achieve this is by articulating that protocol and the documents from which it is composed.
Would it be correct to say that PUT is for replacing the entire entity (resource) and PATCH if for modifying a sub-set of the entity's (resource's) properties?
Not quite. PUT means the message-body of the request is a replacement representation of the resource. PATCH means the message-body of the request is a patch document.
There's nothing in the semantics that prevents you from using PUT to change a single element in a large document, or PATCH to completely replace a representation.
But a client might prefer PATCH to PUT because the patch document is much smaller than the replacement representation. Or it might prefer PUT to PATCH because the message transport is unreliable, and the idempotent semantics of PUT make retry easier.
The right decision also depends on the way other resources are mapped in the project. Same style is better, however if there's no preference, the following could have the advantage of being easier to implement and remember
POST /api/follow/{user-b-id} // to follow
and
POST /api/unfollow/{user-b-id} // to un-follow
I would say, use the delete verb if your are passing in the id of the relationship/link/follow from a to b. This way, it is fairly explicit your route is doing. It is accepting an id of some object and deleting it.
However, in your example, you are passing in the id of the other user, then you have to do some logic to find the relationship/link/follow object between the two and delete it. In my mind, this is more of a post than a delete because of the additional work you have to do. Regardless, it seems fairly subjective as to which one is "right",

RESTful API - DELETE some of a resource collection?

I can DELETE a single resource like:
// Removes group 12 from employee 46
DELETE /employees/46/groups/12
I can DELETE a whole resource collection like:
// Removes all groups from employee 46
DELETE /employees/46/groups
I'm looking for the proper RESTful way to DELETE some of a resource collection.
DELETE /employees/46/groups { ids: [12, 15, 32] }
DELETE /employees/46/groups?ids=12,15,32
DELETE /employees/46/groups/xx (single, but call it 3 times)
Should query string parameters (?ids=12,15,32) only be used with GET..?
Should the request body ({ ids: [12, 15, 32] }) always be used with POST, PUT and DELETE..?
All three of these will work, but which one is the standard way to DELETE only some of a resource collection..?
JSON API uses approach number 1 (DELETE /employees/46/groups with a body). I think that’s fishy, because RFC 7231 § 4.3.5 basically says that the entire target resource (/employees/46/groups) is to be deleted, regardless of what’s sent in the body. However, others disagree.
I think DELETE /employees/46/groups?ids=12,15,32 is best, because it considers the set of groups you want to delete as a resource of its own. You can give links to in your hypermedia. You can later support GET on it (but you don’t have to).
No, there is absolutely nothing preventing you from sending non-GET requests with a query string. The query string is not some kind of “parameter” (although it’s often useful to treat it like that), it’s an integral part of the resource’s URI. In fact, you could use DELETE /api.php?type=employee&id=46&groups=12,15,32 and that would still be perfectly RESTful. The whole point of REST is that URIs (among other things) should be opaque to the client.
However, the query string approach may pose problems when you want to delete a really large number of groups in one request. If that happens, the simplest approach is a POST /bulk-delete-groups RPC call. You may also consider PATCH /employees/46/groups (but please read RFC 5789 errata first).
Most APIs don't allow to delete a collection of resources at a time but it's possible to perform other operations on entities like:
DELETE /employees?id=12,15,32
or
DELETE /employees?id=12&id=15&id=32
A good choice maybe the non-REST way, to send a custom JSON object containing the ID's marked for deletion.

Updating more than one item in a RESTful way

What should be the correct RESTful approach when trying to update/delete more than one item?
Typical example: There is a list of items, the income folder of mails received, where you can select a group of them by setting the appropiate checkboxes. Then you click in the "delete" button and send the petition of delete them. What method should I call? What parameters?
In this case it's pretty obvious I should use a DELETE, but it only works with one item at once. Also, I might not want to delete them, but storing them in a different folder, which might imply using a PATCH, but then again, the PATCH method only allows one item.
In this case it's pretty obvious I should use a DELETE, but it only
works with one item at once. Also, I might not want to delete them,
but storing them in a different folder, which might imply using a
PATCH, but then again, the PATCH method only allows one item.
You should PATCH the collection (or a part of it) and not the item. For example by moving items, you could use PATCH /collection/?filter=x {location: newDir}. The DELETE is a tricky question. You can use the PATCH or an alternative to use the DELETE /collection/?filter=x, but that implies that you want to delete the collection resource instead of removing item resources from it. By batch creation I think using the POST /collection/ [item1, item2, ...] is okay.
Ofc. you can use alternative URI structues too, for example PATCH /books/1+2+3/ {price: 20, currency: "EUR"}. There is an alternative syntax for PATCH too, in that you add the operation name to the body, for example PATCH /collection/?filter=x {op: "update", location: newDir}. I don't like that, but if you want to reuse PATCH with the same URI, then it can become handy. Another alternative to send the request to a single batch endpoint e.g. POST /transactions/ and use a multipart HTTP request.
I think the most important part here to keep in mind, what you are doing is forcing multiple operations into a single transaction. So if you don't need immediate consistency, and losing connection between requests is not a problem, then the client can send multiple requests parallel or series using a simple loop.
You could use matrix parameters for the delete. Given that the parameters are resource IDs you could use unnamed parameters, so for example a DELETE to https://host.com/messages/1;2;3 would remove messages with IDs 1, 2 and 3.