Imagine, We have an Entity School and this entity has a one to many relationship with Student entity. In other words, there is a collection of Students attached to a given School
If we are to replace the entire Student collection via a single API call,
API_URL/school/:school_id/students
which is the best Rest method to go along with. I think PUT is only used on an Entity not on a Collection. Hence, available options would be to use either PATCH or POST
I think PUT is only used on an Entity not on a Collection
No - PUT is used on a resource, not on an entity or collection.
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
The changes that happen to the entities in your domain are a side effect of the manipulation of REST resources. See Jim Webber's talk REST: DDD in the Large.
If your message body is a replacement representation for the resource, then either POST or PUT is the appropriate method to use
If your message body is a patch document, then you should use POST or PATCH.
If you are concerned that POST would be overloaded, then create a new resource in your design to manage this part of your integration protocol.
Again, heed Jim Webber:
URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
I'm facing same issue. My teammates hate none resource nouns in the path. So in order to pass the API design review and to distinct an operation on whole collection from one on a single resource, I go one level up to the school.
GET /schools/1234
{
"schoolMetadat": "xxxx",
"students": []
}
And PATCH on the students property. An update to a property is always replacement.
For updating the entire resource use PUT, for partial update use PATCH.
PATCH API_URL/school/:school_id {students: [...]}
PUT API_URL/school/:school_id/students [...]
PATCH API_URL/school/:school_id/students {add: [...], remove: [...]}
And don't confuse web services in the presentation layer with ORMs in the data access layer.
Related
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",
I would like to know which is the best practice when you are having a resource which contains a list of subresources. For example, you have the resource Author which has info like name, id, birthday and a List books. This list of books exists only in relation with the Author. So, you have the following scenario:
You want to add a new book to the book list
You want to update the name of a book from the list
You want to delete a book from the list
SOLUTION 1
I searched which is the correct design and I found multiple approaches. I want to know if there is a standard way of designing this. I think the design by the book says to have the following methods:
To add: POST /authors/{authorId}/book/
To update: PUT /authors/{authorId}/book/{bookId}
To delete: DELETE /authors/{authorId}/book/{bookId}
SOLUTION 2
My solution is to have only one PUT method which does all these 3 things because the list of books exists only inside object author and you are actually updating the author. Something like:
PUT /authors/{authorId}/updateBookList (and send the whole updated book list inside the author object)
I find multiple errors in my scenario. For example, sending more data from the client, having some logic on the client, more validation on the API and also relying that the client has the latest version of Book List.
My question is: is it anti-pattern to do this?
SITUATION 1. In my situation, my API is using another API, not a database. The used API has just one method of "updateBookList", so I am guessing it is easier to duplicate this behavior inside my API too. Is it also correct?
SITUATION 2. But, supposing my API would use a database would it be more suitable to use SOLUTION 1?
Also, if you could provide some articles, books where you can find similar information. I know this kind of design is not written in stone but some guidelines would help. (Example: from Book REST API Design Rulebook - Masse - O'Reilly)
Solution 2 sounds very much like old-style RPC where a method is invoked that performs some processing. This is like a REST antipattern as REST's focus is on resources and not on methods. The operations you can perform on a resource are given by the underlying protocol (HTTP in your case) and thus REST should adhere to the semantics of the underlying protocol (one of its few constraints).
In addition, REST doesn't care how you set up your URIs, hence there are no RESTful URLs actually. For an automated system a URI following a certain structure has just the same semantics as a randomly generated string acting as a URI. It's us humans who put sense into the string though an application should use the rel attribute which gives the URI some kind of logical name the application can use. An application who expects a certain logical composition of an URL is already tightly coupled to the API and hence violates the principles REST tries to solve, namely the decoupling of clients from server APIs.
If you want to update (sub)resources via PUT in a RESTful way, you have to follow the semantics of put which basically state that the received payload replaces the payload accessible at the given URI before the update.
The PUT method requests that the state of the target resource be
created or replaced with the state defined by the representation
enclosed in the request message payload.
...
The target resource in a POST request is intended to handle the
enclosed representation according to the resource's own semantics,
whereas the enclosed representation in a PUT request is defined as
replacing the state of the target resource. Hence, the intent of PUT
is idempotent and visible to intermediaries, even though the exact
effect is only known by the origin server.
In regards to partial updates RFC 7231 states that partial updates are possible by either using PATCH as suggested by #Alexandru or by issuing a PUT request directly at a sub-resource where the payload replaces the content of the sub-resource with the one in the payload. For the resource containing the sub-resouce this has an affect of a partial update.
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]).
In your case you could therefore send the updated book collection directly via a PUT operation to something like an .../author/{authorId}/books resource which replaces the old collection. As this might not scale well for authors that have written many publications PATCH is probably preferable. Note, however, that PATCH requires an atomic and transactional behavior. Either all actions succeed or none. If an error occurs in the middle of the actions you have to role back all already executed steps.
In regards to your request for further literature, SO isn't the right place to ask this as there is an own off-topic close/flag reason exactly for this.
I'd go with the first option and have separate methods instead of cramming all logic inside a generic PUT. Even if you're relying on an API instead of a database, that's just a 3rd party dependency that you should be able to switch at any point, without having to refactor too much of your code.
That being said, if you're going to allow the update of a large number of books at once, then PATCH might be your friend:
Looking at the RFC 6902 (which defines the Patch standard), from the client's perspective the API could be called like
PATCH /authors/{authorId}/book
[
{ "op": "add", "path": "/ids", "value": [ "24", "27", "35" ]},
{ "op": "remove", "path": "/ids", "value": [ "20", "30" ]}
]
Technically, solution 1 hands down.
REST API URLs consist of resources (and identifiers and filter attribute name/values). It should not contain actions (verbs). Using verbs encourages creation of stupid APIs.
E.g. I know a real-life-in-production API that wants you to
do POST on /getrecords to get all records
do POST on /putrecords to add a new record
Reasons to choose solution 2 would not be technical.
For requirement #2 (You want to update the name of a book from the list), it is possible to use JSON PATCH semantics, but use HTTP PATCH (https://tools.ietf.org/html/rfc5789) semantics to design the URL (not JSON PATCH semantics as suggested by Alexandru Marculescu).
I.e.
Do PATCH on /authors/{authorId}/book/{bookId}, where body contains only PK and changed attributes. Instead of:
To update: PUT on /authors/{authorId}/book/{bookId}
JSON PATCH semantics may of course be used to design the body of a PATCH request, but it just complicates things IMO.
My data access layer supports the upsert operations (Spring Data's CrudRepository.save()), when the id field is not set a new record is inserted and when the id field is set it is updated.
I am wondering how to justify the additional effort required to create two separate REST methods (both on the backend and the frontend side):
POST /users, for creating a new user (and generating the URI of the newly created resource)
PUT /users/{id}, for updating the existing users
over creating just one REST method:
POST /users
Are there any benefits of having two seperate methods other than being more RESTful?
It's more clearer to using different resources for different actions.
By REST ideology - PUT Idempotent method and POST not Idempotent. So each POST request should return new item in response, but PUT should return the same item in response.
I think it's a good when behavior is expected.
But if you write documentation for your api, you can using one resource for both actions (but I would choose the first option).
The data access layer supporting upsert does not mean that the REST API should support it, too. I would not overload POST /users with two meanings. Stick to two different resources.
Edit:
POST /users has the general meaning of 'add a new instance to the resource collection'. I see no way to extend this to '... or update existing instance if an ID is given'. /users is the collection resource, not a single resource you want to manipulate. Doing a POST to a collection resource should manipulate the collection, not a single existing resource.
I'm converting a SOAP based RPC style "web service" to a JSON based REST web service using ASP.NET Web API.
Methods such as AddXYZ / UpdateXYZ / RemoveXYZ map cleanly to the HTTP verbs for POST/PUT/DELETE. Are there any best practices/guidance for mapping typical RPC style operations such as "ExecuteXYZ" or "AssignXYZ" style methods to it's REST counterpart?
My take is that such operations would map to corresponding URL addressable resources such as "ExecuteXYZRequest" and "AssignXYZRequest"
http://myhost/myservice/ExecuteXYZRequest
http://myhost/myservice/AssignXYZRequest
A request to execute "ExecuteXYZ" would then translate to a POST operation.
Getting the submitted request would translate to a GET(typically would be used to get the status of the submitted request).
http://myhost/myservice/ExecuteXYZRequest/1 <--- 1 is the ID of the request
Cancelling the request(assuming it's cancellable) would translate to a DELETE
POST would not really map to anything.
Does the above sound like a reasonable REST implementation or am I totally off in my thinking here?
Thought/guidance much appreciated.
UPDATE
Here is the specific example I'm trying to model:
A many to many relationship between a Contact and an Event entity. What would be the best way to model the membership of a Contact to an Event as a REST resource such that a Contact can be added/ removed from an Event. In the RPC land This would be a method such as "AssignContactToEvent" which takes the IDs of both entities and set up the relationship between these two. How can this be modeled naturally in REST as a resource. I recall that there is a concept of links and "rel" but cannot find a concrete practical example illustrating how to model something like this using Web API
Question is whether it makes sense for the RPC methods to map to REST
resources as indicated in the post
In a nutshell; no, it doesn't make sense to map methods to resources in the way you describe :)
In order to successfully "do REST" we have to think a little differently, and abandon all thoughts of RPC and CRUD-operations; these are really rather limiting once you embrace being RESTful!
The key abstraction of information in REST is a resource. Any
information that can be named can be a resource: a document or image,
a temporal service (e.g. "today's weather in Los Angeles"), a
collection of other resources, a non-virtual object (e.g. 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.
http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
A method or action/verb is then not a resource, so it has no place in a URI -- unless of course you're building an application that allows people to create their own methods, which would be rather unusual!
Taking your specific example for a contacts and events relationship, it's important to understand that your 'AssignContactToEvent' is an action that happens under the Web-API layer and cannot be modelled RESTfully; I hope this will become clear in the course of the following examples :)
First we need some good resources to model a list of all Contacts, and a list of all Events:
/contacts
/events
These resources model an individual Contact or Event identified by an ID-token:
/contacts/{contact_id}
/events/{event_id}
The users of your application want to know who is involved in a particular Event, so we need a resource that models a list of the Event's participants:
/events/{event_id}/participants
When we want to add a Contact to an Event, we could POST a minimal Contact-representation (containing just the Contact-ID) to the Event's participants-list:
POST /events/{event_id}/participants/ HTTP/1.1
Content-Type: application/json
{'id': {contact_id}}
To remove a Contact from an Event:
DELETE /events/{event_id}/participants/{contact_id} HTTP/1.1
Your application-users also want to see at-a-glance the Events a Contact is participating in, so you need another to resource to model this:
/contacts/{contact_id}/events
Similarly, you can now GET a list of Events for the Contact, and assign Events using POST:
POST /contacts/{contact_id}/events/ HTTP/1.1
Content-Type: application/json
{'id': {event_id}}
The important point to take onboard is that whenever you need to model something new, you create a resource. The details of how you store the properties and relationships of data-objects are abstracted away behind a Web-API. Indeed, the data-storage technology might change in future, say from relational to object-store, or you change your programming language or framework, but in all cases your URI's (and Web-API) remain the same. REST and HTTP are designed to endure well-beyond the technologies that run under-the-hood.
As a final example of creating new resources, consider a resource that models a list of Contact's who have an organiser-role:
/events/{event_id}/organisers
or this one that models the list of Events that a Contact is organising:
/contacts/{contact_id}/events-organised
If you have a authentication-system, then you might want to see the events you are attending:
/my-account/events
I hope this helps to clarify the purpose of a Web-API and following RESTful principles.
There are two approaches that I have seen so far.
One is to map the action to a verb if there are very few actions so there is no collision. So if action is not safe nor idempotent then POST, otherwise if not safe but idempotent then PUT:
POST http://myhost/myservice/XYZ
Other is to define the action as a logical resource:
POST http://myhost/myservice/XYZ/Assignment
Later is richer and I favour that.
Few Important Points
RPC Endpoint -> REST Entry Point
RPC read method -> REST GET on Resource
RPC create method -> REST POST operation
PRC delete method -> REST DELETE operation
RPC SOAP Message -> REST PayLoad
additonaly , think about Cache headers , Content-Type headers like #Consumes, #Produces
The task: I have multiple resources that need to be updated in one HTTP call.
The resource type, field and value to update are the same for all resources.
Example: have set of cars by their IDs, need to update "status" of all cars to "sold".
Classic RESTFul approach: use request URL something like
PUT /cars
with JSON body like
[{id:1,status:sold},{id:2,status:sold},...]
However this seems to be an overkill: too many times to put status:sold
Looking for a RESTful way (I mean the way that is as close to "standard" rest protocol as possible) to send status:sold just once for all cars along with the list of car IDs to update. This is what I would do:
PUT /cars
With JSON
{ids=[1,2,...],status:sold} but I am not sure if this is truly RESTful approach.
Any ideas?
Also as an added benefit: I would like to be able to avoid JSON for small number of cars by simply setting up a URL with parameters something like this:
PUT /cars?ids=1,2,3&status=sold
Is this RESTful enough?
An even simpler way would just be:
{sold:[1,2,...]}
There's no need to have multiple methods for larger or smaller numbers of requests - it wastes development time and has no noteable impact upon performance or bandwidth.
As far as it being RESTful goes, as long as it's easily decipherable by the recipient and contains all the information you need, then there's no problem with it.
As I understand it using put is not sufficient to write a single property of a resource. One idea is to simply expose the property as a resource itself:
Therefore: PUT /car/carId/status with body content 'Sold'.
Updating more than one car should result in multiple puts since a request should only target a single resource.
Another Idea is to expose a certain protocol where you build a 'batch' resource.
POST /daily-deals-report/ body content {"sold" : [1, 2, 3, 4, 5]}
Then the system can simply acknowledge the deals being made and update the cars status itself. This way you create a whole new point of view and enable a more REST like api then you actually intended.
Also you should think about exposing a resource listing all cars that are available and therefore are ready for being sold (therefore not sold, and not needing repairs or are not rent).
GET /cars/pricelist?city=* -> List of all cars ready to be sold including car id and price.
This way a car do not have a status regarding who is owning the car. A resource is usually independent of its owner (owner is aggregating cars not a composite of it).
Whenever you have difficulties to map an operation to a resource your model tend to be flawed by object oriented thinking. With resources many relations (parent property) and status properties tend to be misplaced since designing resources is even more abstract than thinking in services.
If you need to manipulate many similar objects you need to identify the business process that triggers those changes and expose this process by a single resource describing its input (just like the daily deals report).