Reputation: 2593
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.
POST /users/{userId}/books
or PUT /users/{userId}/books
or PATCH?
or POST /users/{userId}/books/concatenate
POST /users/{userId}/books
or PUT /users/{userId}/books
or PATCH?
or POST /users/{userId}/books/merge
POST /users/{userId}/books/delete?category=x
or DELETE /users/{userId}/books?category=x
POST /users/{userId}/books/delete_all
or DELETE /users/{userId}/books
Would be thankful for some hints or guidelines
Upvotes: 0
Views: 783
Reputation: 57257
"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."
Upvotes: 1