This is a follow up question to :
Transactions in REST?
How does one implement a REST API that offers full transaction capabilities to it's clients?
For example, if a client wants to create a transaction that will do the following operations:
create one or more objects.
update one or more objects.
delete one or more objects.
While it's a valid requirement for a transaction, it seems to break the REST requirements to use PUT to create, POST to update and DELETE to delete.
My current solution involves handling the entire system as one hierarchical object structure and using the POST operation. For example:
POST /system
{
"Users" : [
{
"ID":"123",
"name":"bob"
// update the user with ID matching 123,
// set his name to "bob"
},
{
"ID":"456",
"delete":"true"
// trigger a delete on user with ID 456
}
],
"Products" : [
{
"name":"foo"
// create a product named "foo" since no ID is provided
},
]
}
So far, this satisfies most REST requirements except for the "delete" flag which isn't really a piece of data.
I'm curious to know if anyone found a better solution.
Agree With Jan that you need to handle at the serverside.but down side is badly maintainble code.Yes my experience with Restful applications suggest that adhering to PUT & DELETE verbs in RESTFul Architecture is pretty tough as various browser version support is far limited for them.
Related
I am looking to expose some domain RESTful APIs on top of an existing project. One of the entities I need to model has a single document: settings. Settings are created with the application and is a singleton document. I'd like to expose it via a well-designed resource-based RESTful API.
Normally when modeling an API for a resource with many items its something like:
GET /employees/ <-- returns [] of 1-* items
GET /employees/{id}/ <-- returns 1 item
POST /employees/ <-- creates an item
PUT /employees/{id}/ <-- updates all fields on specific item
PATCH /employees/{id}/ <-- updates a subset of fields specified on an item
DELETE /employees/{id}/ <-- deletes a specific item
OPTION 1: If I modeled settings in the same way then the following API is built:
GET /settings/ <-- returns [] of 1-* items
[{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }]
GET /settings/{id}/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }
PUT /settings/{id}/
PATCH /settings/{id}/
This to me has a few nuances:
We return an array when only 1 item CAN and EVER WILL exist. Settings are a singleton that the application creates.
We require knowing the id to make a request only returning 1 item
We require the id of a singleton just to PUT or PATCH it
OPTION 2: My mind then goes in this direction:
GET /settings/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }
PUT /settings/
PATCH /settings/
This design removes the nuances brought up below and doesn't require an id to PUT or PATCH. This feels the most consistent to me as all requests have the same shape.
OPTION 3: Another option is to add the id back to the PUT and the PATCH to require it to make updates, but then an API user must perform a GET just to obtain the id of a singleton:
GET /settings/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }
PUT /settings/{id}/
PATCH /settings/{id}/
This seems inconsistent because the GET 1 doesn't have the same shape as the UPDATE 1 request. It also doesn't require a consumer to perform a GET to find the identifier of the singleton.
Is there a preferred way to model this?
Does anyone have any good reference material on modeling RESTful APIs for singleton resources? I am currently leaning towards OPTION 2 but I'd like to know if there are good resources or standards that I can look into.
Is there a compelling reason to require an API consumer to make a GET for the id of a resource to then use it in an update request, perhaps for security reasons, etc?
The ID of the Resource is the Url itself and not necessarily a Guid or UUID. The Url should uniquely IDentify the Resource, in your case the Settings entity.
But, in order to be RESTfull, you must point to this resource in your index Url (i.e. the / path) with an appropriate rel attribute, so the client will not hardcode the Url, such as this:
GET /
{ ....
"links": [
{ "url" : "/settings", "rel" : "settings" }
], ...
}
There are no specifics to accesing a singleton resource other than the Url will not contain a Guid, Uuid or any other numeric value.
Option 2 is perfectly RESTful, as far as I can tell.
The core idea behind RESTful APIs is that you're manipulating "resources". The word "resource" is intentionally left vague so that it can refer to whatever is important to the specfic application, and so that the API can focus only on how content will be accessed regardless of what content will be accessed.
If your resource is a singleton, it does not make sense to attribute an ID value to it. IDs are very useful and commonly used in RESTful APIs, but they are not a core part of what makes an API RESTful, and, as you have noticed, would actually make accessing singleton resources more cumbersome.
Therefore, you should just do away with IDs and have both
GET /settings/
and
GET /settings/{id}
always return the settings singleton object. (access-by-id is not required, but it's nice to have just in case someone tries it). Also, be sure to document your API endpoint so consumers don't expect an array :)
Re: your questions,
I believe option 2 would be the preferred way of modeling this, and I believe requiring your consumer to make a GET for the id would actually be somewhat of an anti-pattern.
I think the confusion here is because the word settings is plural, but the resource is a singleton.
Why not rename the resource to /configuration and go with option 2?
It would probably be less surprising to consumers of your API.
You're probably overthinking it. There's no concept of singleton in HTTP or REST.
GET /settings/ is perfectly fine.
By the way, we can hardly relate this to DDD - at least not if you don't give more context about what settings means in your domain.
It might also be that you're trying to tack an "Entity with ID" approach on Settings when it's not appropriate. Not all objects in a system are entities.
I have an entity with several attributes, say «project». Apart from simple attributes, the project may have a list of «statuses» of which the last one is the current one. I have a web form to create/edit a project. All attributes of this project can be changed in this form, and also users can add a new status for the project (but they can’t change or delete old statuses).
Project statuses are purely composite entities, they don’t have any distinctive meaning or identity outside of the project scope, and they are not to be addressed directly, so they obviously don’t deserve a special root REST resource.
According to REST architecture, I created a resource called /projects. POST is used to create a new project, and PUT is used to change an existing project.
However, I don’t want the client to PUT the project together with all its historical statuses, firstly because this collection is too heavy, and secondly because the business logic allows only for adding statuses, not changing or deleting them, so PUTting the project together with all of its statuses doesn’t make any sense anyway.
PUTting a project with only a new status is also not an option, because it violates the idempotency of PUT.
I also don’t like the idea of POSTing a status in a second HTTP-request, say /project/{id}/status, because that would break the atomicity of the update operation from the user’s standpoint. If this second request gets lost on the wire, then the project will appear inconsistent to the user who edited it (the attributes changed, but the status stayed the same). Creating RESTful "transactions" seems like overkill (and also error prone) for this simple task of updating a seemingly monolithic entity.
This kind of problem is quite ubiquitous in my work, and may be generalized as such: what is the RESTfully correct and atomic way of updating a complex composite entity for which only partial update is allowed by the business logic?
I think that if you want to do partial updates (it's actually your case), you should use the method PATCH. This allows to update either the project without dependencies (statuses) or the dependency(ies) without the project hints.
You can notice that there is a format to describe the operations to do within a method PATCH. It's called JSON Patch (see https://www.rfc-editor.org/rfc/rfc6902). This format describes what you want to do within your request: add an element, update it, remove it, ...
I think that you could have something like that if you want (for example) to update the name of a specific project, remove a status (it's also a sample since I read that you want to forbid this!) and add a new one in one atomic request:
PATCH /projects/1
[
{
"op": "replace",
"path": "/name",
"value": "the new name of the project"
},
{
"op": "remove",
"path": "/statuses/1"
},
{
"op": "add",
"path": "/statuses/",
"value": {
"name": "my status",
(...)
}
}
]
Notice that you can put what you want in the attribute name to identify the related element in the resource state. So /statuses/1 can be the second element in the array, the status with id of value 1 or something else.
The server-side processing for the request can be atomic.
I wrote a blog post about bulk updates: https://templth.wordpress.com/2015/05/14/implementing-bulk-updates-within-restful-services/. I think that the section "Implementing bulk updates" could correspond to what you look for.
Hope it helps you,
Thierry
Do you need HTTP PATCH? It is the verb to express delta updates to a resource.
https://www.rfc-editor.org/rfc/rfc5789
is it possible to enumerate all instances of a resource without voilating rest principles in a single call.
Say I want to enumerate all the student information using one call.
GET /students
With REST principles this call is returning:
"students": [{
"uri":"/student/1"
},
{
"uri":"/student/2"
},
]
What I want is to use a single call to get all the data:
GET /student
"students": [{
"name":"x",
"moreInfo":...,
"uri":"/student/1"
},
{
"name":"y",
"moreInfo":...,
"uri":"/student/2"
}, ]
This would not violate HTTP principles. Whether it is a good idea or not though is a question for your resource hierarchy, based on what you are trying to do. Such a setup would have a students resource that holds the data for all students. There would be no need then for an individual student record (eg GET /students/:id). The client might get annoyed if this returned a huge amount of data though, and it is pushing the processing of the data onto the client. Say the client only wants one student. It has to parse the entire student population, ignoring all the irrelevant data, to get to the one student it wants. Of course if the client needs all the student data then this isn't an issue.
So really the issue is not how RESTful this is, but why you want to do it and whether it is the right thing for the client of your system. What hierarchy is the client expecting. If this fits then by all means go for it.
Suppose I have a resource called user_stats, that has things like how many posts, comments, likes, and followers users have. Is there a RESTful way to only ask for parts of that statistics (i.e. for user_stats/3, tell me how many posts and comments this user has, but don't tell me how many follower this user has.)
The reason I'm asking is some statistical attributes can be computationally intensive (yes I'm generating them at query time). So simply not asking for it can reduce workload.
There is a very useful 38 page free ebook with best practices about designing Web APIs, you might find it helpful, at least I did.
For your case, it is stated:
Add optional fields in a comma-delimited list
The Google approach works extremely well.
Here's how to get just the information we need from our dogs API using
this approach:
/dogs?fields=name,color,location
It's simple to read; a developer can select just the information an
app needs at a given time; it cuts down on bandwidth issues, which is
important for mobile apps. The partial selection syntax can also be used to include associated resources cutting down on the number of requests needed to get the required information.
Maybe that's what you re looking for?
there are at least three options:
Use query parameter as a filter
e.g. user_stats?fields=posts,comments
Make user_stats composite resource and create new resources for particular stat
e.g. /user_stats in JSON
{
"blogs" : {
"count" : 10,
"link" : "/user_stats_blobs"
},
...
}
then you can get whole stats (GET /user_stats) or just a piece (GET /user_stats_blobs)
Create filter representation; use POST to post filter representation as part of request
e.g.
Request
POST /user_stats/filter
{
"fields" : [ "blogs", ...]
}
response body contains just requested/filtered data.
All solutions are RESTful. Solution 1. is easy to implement but has limited extensibility and transparency. Solution 2. expects that you create new resources which is overhead in this case (you need just one number). so, I would recommend solution 3. because is no so hard to implement, is easily extensible and transparent.
I have a small REST API that is being consumed by a single page web application powered by Backbone.js
There are two resource types that the API provides, and therefore, the Backbone app uses. These are articles and comments. These two resources have different endpoints and there is a link from each of the articles to the location of all the comments for that item.
The problem that I'm facing is that, on the article list in my web app I would like to be able to display the number of comments for each article. Given that that would only be possible if I also get the comments list, on the current setup, would require me to make one API request to get the the initial article list and another one for each of the articles to be able to count the number of comments. That becomes a problem if, for instance, there are 100 articles, and therefore 101 HTTP requests would be necessary to populate one single view.
The solutions I can think of right now are:
1. to include the comments data in the initial articles request like so
{
{
"id": 1,
"name": "Article 1",
...
"comments": {
{
"id": 1,
"text": "some comment"
},
{
"id": 2,
"text": "some comment"
},
...
}
},
}
The question in this case is: How is it possible to parse the "comments" as a separate comments collection and not include it into the article model?
2. to include some metadata inside the articles response like so:
{
{
"id": 1,
"name": "Article 1",
...
"comments": 13
},
}
Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?
I feel there might be another solution, compliant with the REST philosophy, for this that I'm missing, so if you have any other suggestion please let me know.
I think your best bet is to go with your second option, include the number of comments for each article inside your article model.
Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?
Not sure what your concern is here. Why would you be worried about the comments attribute getting updated?
I can't think of any other "RESTy" way of achieving your desired result.
I would suggest using alternative 2 and have the server return
a subset of the article attributes that are deemed useful for
applications when dealing with the article collection resource
(perhaps reachable at /articles).
The full article member resource with all its comments (whether
they are stored in separate tables in the backend) would be
available at /articles/:id).
From a Backbone.js point of view you probably want to put the
collection resource in a, say, ArticleCollection which will
convert each member (currently with a subset of the attributes)
to Article models.
When the user selects to view an article in full you pull it
out from the ArticleCollection and invoke fetch to populate
it in full.
Regarding what to do with extra/virtual attributes that are included
in the collection resource (/articles) like the comment count and
possibly other usefult aggregations, I see a few alternatives:
In Article#initialize you can pull those out from the attributes
and store them as meta-data on the article. This way the built-in
Backbone.Model#toJSON will not see them.
Keep them in the attributes section of each model and override
Backbone.Model#toJSON to exlcude them when "serializing" an Article.
In atlernative 1, an Article#commentCount() helper could return
this._commentCount || this.get('comments').length to make it work
on both partially and fully loaded articles.
For a fully loaded Article you would probably want to convert the
nested comments array into a full-blown CommentCollection anyway
and store that in this._comments so I don't think it is that unusual
to have your models store additional stuff directly on the model instance,
outside of its attributes hash.