Lets say I have a rest service that allows applications to create User object
URI: /users
HTTP Method:POST
{
"firstName":"Edward",
"lastName": "Nygma",
"dob": "01011981",
"email": "en#gc.com",
"phone": "0123456789"
}
On the first POST the User object is created and and the User ID is returned
Lets say there is a second service that allows the user to update the lastName and email fields.
URI: /user/1/last-email
HTTP Method: POST
{
"lastName": "scissorhands",
"email": "ec#bc.com"
}
Let's say for the sake of bandwidth sending the full User object is not an option for this update call.
Is this the correct way to do a partial update that involves several fields? Also using PATCH is out of the question.
Edit:
I know that the correct way to do this restfully would be to post an update to each field as a sub resource but lets say for the sake of bandwidth/business requirements that this update has to be done in a single call. Is this the correct way to do so?
Edit 2:
Our implementation does not support the HTTP PATCH method, hence why I indicated in the initial question that using patch is out of the question. That being said, maybe I should rephrase the question.
Since system/business requirements prevent us from implementing this correctly in a RESTful manor. What is the best way to handle this scenario.
Putting the verb "update-" suddenly makes it feel like it's an RPC call. What do you do when you want to delete this email? Doing a DELETE action on this URI looks a bit silly.
URI: /user/1/email and
URI: user/1/lastname would make more sense as EMAIL would just be a subresource and you can use all the verbs on those resources.
Yes, this would take 2 calls in case you want to update 2 resources instead of 1.
For partial updates of a resource use "PATCH" verb on the resource. This way you would not need a new URI at all. (Best practice for partial updates in a RESTful service)
Reference: http://restcookbook.com/HTTP%20Methods/patch/
Quote:
When should we use the PATCH HTTP method?
The HTTP methods PATCH can be used to update partial resources. For instance, when you only need to update one field of the resource, PUTting a complete resource representation might be cumbersome and utilizes more bandwidth
See more at: http://restcookbook.com/HTTP%20Methods/patch/#sthash.jEWLklrg.dpuf
Related
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.
I have a timespan I want to delete in a REST API.
It doesn't have an id so calling HTTP DELETE on "/timespan/" is not really possible. The implementation would be possible, but I would rather not put in the extra effort (requires some database modifications) unless there is a good reason to add it.
I considered calling DELETE on "/timespan/" with "start" and "end" inside the request but to my understanding this clashes with the way REST works.
Is it legit to call DELETE on "/timespan//" or maybe a concatenation such as "/timespan/+" or should I implement IDs after all?
You are correct. DELETE doesn't take a body.
RFC 7231:
A payload within a DELETE request message has no defined semantics;
sending a payload body on a DELETE request might cause some existing
implementations to reject the request.
I've seen what you want done as
DELETE /sites/{siteId}/maintenance
but that's really not optimal. If maintenance is a resource, it needs some way of being uniquely identified. If it's a property of a resource, then you delete it via PUT or PATCH on that resource.
Assuming your resource is a maintenance performed on a site. The API could have:
DELETE /sites/{site-id}/maintenances/{maintenance-id} to delete one maintenance. The typical delete.
DELETE /sites/{site-id}/maintenances to delete all maintenances of a given site. Not usual, and dangerous.
DELETE /site/{site-id}/maintenances?start={start-date}&end={end-date} to delete all maintenances in a timespan. The answer to your question.
Rationale: the timespan is not part of the resource, it's a filtering attribute on the collection of resources. Therefore, it should not be part of the URI (Uniform Resource Identifier). We should use query string parameters for filtering.
Another option:
POST /site/{site-id}/clean-up to delete all maintenances of a given site that are within the timespan specified in the request body. Also an answer to your question.
Rationale: some advocate that a REST API can offer more "coarse-grained" operations that closely resemble the business capability in complement to (or in the place of) more CRUD-like APIs. Here's a reference. In the particular case, the POST operation executes a "clean-up business process". The start and end dates go in the request body. The operation should return 200 (not 201) for success.
Instead of designing a low-level CRUD-like REST API and let the callers know details about your domain, you could let the client POST their intent and let the server decide what to delete. Seems like the right approach if you ant to prevent users from accidentally (maliciously?) deleting resources. More in Fine grained CRUD resources versus Coarse Grained resources at http://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling
If you are following the RESTful principle closely, you would need to retrieve a list of resources (partial as proposed by #moonwave99) and invoke DELETE on every resource whose timestamp is older than a certain threshold. This conveis the semantics of delete while being completely idempotent. You, however, need a resource identifier therefore (which you should have obtained via the previous retrieve).
The next choice would be to set off a PUT request where you send each and every entry that should be available after the request within that request. In practice this is however a no-go as to much data would need to be transfered.
Last but not least, you would have the possibility to delete resources via PATCH where you pass the necessary instructions to the server it needs to transform the resource(s) from state_before to state_after. In case of json-patch you have the remove operation at hand. However, the spec does not provide any possibility to remove a state if a certain condition was met - a combination of test+delete would be handy in that case. The quintesence is though, that not the server is responsible for filtering out certain data but the client which has to send each necessary step to the server. Therefore, a client has to retrieve the current state of a resource collection like /api/sampleResources which could be an array of JSON objects and do the decission locally:
HTTP/1.1 200 OK
...
ETag: "7776cdb01f44354af8bfa4db0c56eebcb1378975"
...
[
{
...
"timestamp": "2015-07-17T19:40:00",
...
},
{
...
"timestamp": "2014-10-05T10:00:00",
...
},
{
...
"timestamp": "2015-07-16T15:00:00",
...
},
{
...
"timestamp": "2014-12-31T00:00:00",
...
}
]
If all entries from the last year should be deleted, a JSON-PATCH request would need to look like this:
PATCH /api/sampleResources
...
ETag: "7776cdb01f44354af8bfa4db0c56eebcb1378975"
...
[
{ "op": "remove", "path": "/1" },
{ "op": "remove", "path": "/3" }
]
The path is specified in JSON Pointer notation and is 0 based, therefore the sample above removes the second and fourth entry of the list, which are the entries of 2014.
As the resource can be modified between the lookup and the patch generation, it is highly recommended to use ETag features to gurantee that the patch is executed on the right state. If the ETags do not match, the request fails with a precondition failure.
Note however, that PATCH is not idempotent! So sending the same request twice may delete more entries as intended. This is not the case with PUT, as the state after the request is exactly the state you told the resource to have. Therefore, sending the same request twice does not change anything state-wise. In comparison to a bunch of DELETE requests, PATCH is atomic - either all or none of the operations are executed, while the DELETE requests are all independent.
I agree strongly, that there is a need for conditional and partial PUT and DELETE operations to adhere to the business needs. For simplicity reasons I would really recommend to use partial GET and DELETE operations instead of PUT or PATCH.
I have two models in Django:
class Thread(models.Model):
entity = models.ForeignKey(Entity, null=True, blank=True)
...
class ThreadMessage(models.Model):
thread = models.ForeignKey(Thread, related_name='messages')
author = models.ForeignKey(User)
...
Now a client wants to create a new thread with first message in it. It has first to do a POST /threads to create a new thread and find out its id and then do POST /messages passing the found id in thread field.
I am thinking if it's reasonable and possible to do all of this in one request from Ember like:
POST /messages
{"message": {"text": "text", ...},
"thread": {"entity": 1}}
And the response would be:
{"message": {"text": "text", "id": 5678, "thread": 1234, ...},
"thread": {"entitity": 1, "id": 1234, ...}}
Yes it is perfectly reasonable.
People seem to interpret REST in a very strange and largely ignorant way. A cursory read of the HTTP RFC 7231 for POST and PUT will confirm you are on solid ground.
A resource representation can represent ANYTHING. The key thing is to preserve the semantics of the REST operations. So PUT can be used for both CREATE and REPLACE like operations (I tend to think of PUT being REPLACE rather than UPDATE as REPLACE is closer to an idempotent semantic than UPDATE in my mind)
A PUT to an endpoint where supported, should accept whatever representation a GET returns. A POST can do literally anything you want as it doesn't need to support idempotent semantics.
HTTP and REST is designed and intended to support resource representations that may overlap other resources and the RFC is explicit about this. You do this all the time when doing a GET on a collection endpoint.
You are NOT breaking REST by having a thread containing a child message in a single request and IMO that is a very valid use use case for sane referential integrity on the server. Any time a transactional semantic is required, a POST or PUT is perfectly valid to create a graph of objects on the server in a single request. It is really simple, if you can GET it in a single request, you should be able to PUT it in a single request, so think carefully about your URL's and parameters.
For example, you may have a thread endpoint that returns all messages and that endpoint may support a parameter to just return some subset of the information /api/threads?include=hasRead which returns just id and hasRead for each message in the thread, or perhaps just some range of 'pages'. You can then PUT using that same endpoint and parameters and just update thehasRead property in bulk.
Anyone who gets hung up on this has probably never considered access controls either. Access control necessitates a different view of a resource from one user to another based on what they are allowed to access. This different view of a resource is conveyed in HTTP auth headers and/or in the request URL; again REST is not being broken by sub-setting or overlapping resources.
So go ahead and create the minimal graph of objects you need and either PUT or POST them. I use V4 UUID's so clients can assign ID's (and thus resource endpoints) themselves and this allows me to use PUT for both create and replace like actions and wire up complex object graphs without client<->server id mapping issues.
What you are trying to do will be break concept of REST and EmberJS itself.
If you have two separate APIs you should make two REST calls.
First save the parent thread model , after successful return save the child message. Then use addObject to reflect changes in views.
This is best way. Don't try to optimize by reducing API calls here and breaking REST in the way.
I've seen tons of examples on how to structure URL's for basic CRUD operations but seen very little when talking about more Command-like operations, or application service calls.
For example, let's say in my application service I have a call like RemoveOldOrders(int customerId) that would remove any order from the system that is over 2 years old for a customer with id "customerId". What would the URL look like on my restful service? What would the payload of the call look like? What HTTP method (POST?) would I use?
My thought is it would be something like this:
/Customer/1/RemoveOldOrders as a POST, with an empty body (as the customerID would come from the url).
Are there good guidelines on something like this?
Update: I feel like I need to clarify my question a bit in lieu of the comment about a possible duplicate post (yes, that post is asking essentially the same thing but I don't really feel the question was answered well).
What if I want to perform an operation against a resource but that operation doesn't fit into the standard HTTP verbs?
Another example: my application is hooked into an ESB and there needs to be a way to force a projection of my resource onto the ESB for processing? In my current SOAP-based web service I'd have a method like:
ExportCustomer(int customerId)
Now, in the case of a RESTful service, how could I represent this action in a uri? Option 1 from Brian Kelly's answer seems like the most logical, something like:
POST http://someapp/api/customer/1/export
or would:
POST http://someapi/api/customer/export/1
be better?
Anytime you want to model verbs like "remove", you should think of DELETE. Similarly, for "create" think POST (and/or maybe PUT), for "read" think GET and for "update" think PUT (or maybe PATCH).
So for your example of "remove old orders", you should definitely use DELETE. Now your only remaining challenge is how to identify the orders that should be removed. Once you figure that out, the URI scheme will fall into place with it.
Here are some options:
DELETE http://your-api.com/old-orders
Here, the meaning and range of old-orders will be determined by the server receiving this request. This frees the client from having to do so, but removes their ability to change that range.
GET http://your-api.com/order-query?days-older-than=730
This returns a Location URI of http://your-api.com/order-query-result/{some ID} that represents the set of old appointments. Then you can simply issue a DELETE on that URI to purge the old records in one fell swoop.
Instead of forcing the client to remember to issue deletion commands of this type, offer some kind of configuration resource that can be manipulated via your API to set some field like purgeRecordsOlderThanDays=730, and just let the server do it automatically for you in a cron-like fashion. That would be my preferred approach.
For exporting, then you need to remove the "export" verb and replace it with an ESB representation of the resource: -
GET http://someapp/customer/{id}
The response includes a link to export: GET http://someapp/customer/{id}/ESB
Getting on the export link returns the ESB representation (with appropriate content type)
For example, let's say in my application service I have a call like
RemoveOldOrders(int customerId) that would remove any order from the
system that is over 2 years old for a customer with id "customerId".
What would the URL look like on my restful service? What would the
payload of the call look like? What HTTP method (POST?) would I use?
RemoveOldOrders(int customerId)
DELETE /oldOrders {customerId: id}
DELETE /customer/{id}/orders?old=true
etc...
You should read more about uniform interface / resource identifiers and the HTTP method specification.
The URL does not really matters. What matters that you should have resource with resource identifiers (URLs) and you have to manipulate them by using an uniform (standard) interface, like the call of HTTP methods.
I'm building a collection of RESTful resources that work like the following: (I'll use "people" as an example):
GET /people/{key}
- returns a person object (JSON)
GET /people?first_name=Bob
- returns a list of person objects who's "first_name" is "Bob" (JSON)
PUT /people/{key}
- expects a person object in the payload (JSON), updates the person in the
datastore with the {key} found in the URL parameter to match the payload.
If it is a new object, the client specifies the key of the new object.
I feel pretty comfortable with the design so far (although any input/criticism is welcome).
I'd also like to be able to PUT a list of people, however I'm not confident in the RESTfulness of my design. This is what I have in mind:
PUT /people
- expects a list of objects in JSON form with keys included in the object
("key":"32948"). Updates all of the corresponding objects in the datastore.
This operation will be idempotent, so I'd like to use "PUT". However its breaking a rule because a GET request to this same resource will not return the equivalent of what the client just PUT, but would rather return all "people" objects (since there would be no filters on the query). I suspect there are also a few other rules that might be being broken here.
Someone mentioned the use of a "PATCH" request in an earlier question that I had: REST resource with a List property
"PATCH" sounds fantastic, but I don't want to use it because its not in wide use yet and is not compatible with a lot of programs and APIs yet.
I'd prefer not to use POST because POST implies that the request is not idempotent.
Does anyone have any comments / suggestions?
Follow-up:::
While I hesitated to use POST because it seems to be the least-common-denominator, catch-all for RESTful operations and more can be said about this operation (specifically that it is idempotent), PUT cannot be used because its requirements are too narrow. Specifically: the resource is not being completely re-written and the equivalent resource is not being sent back from a GET request to the same resource. Using a PUT with properties outside of it's specifications can cause problems when applications, api's, and/or programmers attempt to work with the resource and are met with unexpected behavior from the resource.
In addition to the accepted answer, Darrel Miller had an excellent suggestion if the operation absolutely had to be a PUT and that was to append a UUID onto the end of the resource path so an equivalent GET request will return the equivalent resource.
POST indicates a generic action other than GET, PUT, and DELETE (the generic hashtable actions). Because the generic hashtable actions are inappropriate, use POST. The semantics of POST are determined by the resource to which an entity is POSTed. This is unlike the semantics of the generic hashtable methods, which are well-known.
POST /people/add-many HTTP/1.1
Host: example.com
Content-Type: application/json
[
{ "name": "Bob" },
{ "name": "Robert" }
]
Using PUT is definitely the wrong verb in this case. POST is meant to do exactly what you are asking. From the HTTP specification:
The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource...
As such, if you want to update multiple resources in a single call, you have to use POST.
Just be cause PUT is required to be idempotent and POST is not, does not mean that POST cannot be idempotent. Your choice of HTTP verb should not be based on that, but based on the relationship of the requested resource and the resource acted upon. If your application is directly handling the resource requested, use PUT. If it is acting on some other resource (or resources, as in your case), use POST.
I really don't see any easy way you could use PUT to create an arbitrary set of people. Unless, you are prepared to have the client generate a GUID and do something like,
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
On the server side you could take the people from the list and add them to the /People resource.
A slight variation to this approach would be to get the server to include a link such as
<link rel="AddList" href="/PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}"/>
in the People resource. The client would need to know that it needs to PUT a list of people to the AddList link. The server would need to make sure that each time it renders the /People resource it creates a new url for the AddList link.
Regarding Darren Miller's suggestion of using PUT to a GUID (I can't comment...), the point of using PUT would be to achieve idempotency for the operation. The litmus test if idempotency would be this conversation between the client and server:
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
204 NO CONTENT (indicates that it all went well)
client loses connection and doesn't see the 204
client automatically retries
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
How would the server differentiate the two? If the GUID is "used up" so to speak then the server would have to respond 404 or 410. This introduces a tiny bit of conversational state on the server to remember all the GUIDs that have been used.
Two clients would often see the same I guess, because of caching or simply keeping stale responses around.
I think a smart solution is to use POST to create an (initially empty, short lived) holding area for a resource to which you can PUT, i.e. clients need to POST to create the GUID resource instead of discovering it via a link:
POST /PeopleList/CreateHoldingArea
201 CREATED and Location: /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
This would mean that the lost idempotency would not result in much overhead; clients simply create new GUIDs (by POSTing) if they didn't see the initial 201 CREATED response. The "tiny bit of conversational state" would now only be the created but not yet used holding areas.
The ideal solution would of course not require any conversational state on the server, but it eludes me.