Guide to designing complex API that works in a RESTful way? - api

I have tried out the RESTful API concept and found out that its a great mindset for building resources APIs. For example, adding comment to post would be
POST /posts/{id}/comments
However, there are some cases, correct me if I am wrong, that the expected APIs can not really be model as a simple CRUD
For example, adding product to the system requires adding picture, adding multiple tags specify its category?
How do I do this the restful way?
1.) Do I force the API user to follow after multiple API calls?
POST /pictures -- add picture
GET /categories -- get selected category
POST /tags -- add tags
POST /products -- input picture, category, tags ids as JSON fields
2.) Do I use nested object which automatically do find all subresources?
POST /products -- input nested JSON array with picture/category/tags object field
In this case, all subresources will be existing resources instead of some (picture, tags) that should be posted.
Also, what would happen if adding picture succeed internally but adding tags failed?
3.) Do I just do a casual API? How does this fit with REST? Doesn't this break the RESTful idea?
POST /add_products
Is there any guide to deal with complex API for RESTful APIs?
Thank you.

In my opinion, one of the biggest misconception people have about REST is that internal models (tables in db or document in mongo) and REST resources must be same. REST resources can be a real model or it can be an abstract entity as well which might not exist in db.
So in this case, your url with POST i.e. POST /products request is perfectly alright as far as REST is concerned. And advice from my personal experience - One doesn't needs to be too dogmatic about url as long as basic principles of REST are conserved such as
Use right HTTP verbs
Use right status codes
Cacheable architecture
Unique indentification of resource by url
Hypermedia (if you can go that far)

Related

URIs in REST API endpoints according to Restful practices

I am planning to have these endpoints for our REST APIs.
PUT /tenant/:tenantId/users/save/:username
POST /tenant/:tenantId/users/invite
GET /tenant/:tenantId/users/fetch
GET /tenant/:tenantId/users/fetch/:username
PATCH /tenant/:tenantId/users/activate/:username
POST /tenant/:tenantId/groups/save/
Verbs such as save/fetch/activate are from the consistency point of view. Are these RESTFul according to the REST principles? How should these be changed if at all? Any recommendations?
According to this REST Resource Naming Guide:
RESTful URI should refer to a resource that is a thing (noun) instead of referring to an action (verb) because nouns have properties which verbs do not have – similar to resources have attributes.
And also
URIs should not be used to indicate that a CRUD function is performed. URIs should be used to uniquely identify resources and not any action upon them. HTTP request methods should be used to indicate which CRUD function is performed.
So let's take your first URI as example
PUT /tenant/:tenantId/users/save/:username
Here you are using the verb save. As mentioned before you should not be indicating a CRUD operation in the URI, in this case using a POST would be more appropriate.Here is a guide with the purpose of each HTTP verb. Knowing this, I think that for example a more appropriate URI for that case would be something like
POST /tenants/:tenantId/users/:username
In this cases:
GET /tenant/:tenantId/users/fetch
GET /tenant/:tenantId/users/fetch/:username
you should remove the fetch because you are already telling through the GET verb that data is being fetched. Same goes for the 6th example.
But, this doesn't mean that you can't use verbs in your URIs, in fact there is a specific category called controller which as mentioned in the same guide:
A controller resource models a procedural concept. Controller resources are like executable functions, with parameters and return values; inputs and outputs.
Use “verb” to denote controller archetype.
This controllers resources could go well (I asume) with for example your
GET /tenant/:tenantId/users/activate/:username.
But I would think that the verb activate should go last:
GET /tenant/:tenantId/users/:username/activate
First note: REST doesn't care what spelling conventions you use for your resource identifiers. Once you figure out the right resources, you can choose any identifiers for them that you like (so long as those identifiers are consistent with the production rules defined in RFC 3986).
"Any information that can be named can be a resource" (Fielding, 2000), but its probably most useful to think about resources as abstractions of documents. We use HTTP as an application protocol whose application domain is the transfer of documents over a network.
GET
This is the method we use to retrieve a document
PATCH
PUT
POST
These methods all indicate requests to edit a document (specifically, to edit the request target).
PUT and PATCH are each ask the server to make its copy of a document look like the client's local copy. Imagine loading a web page into an editor, making changes, and then "saving" those changes back to the server.
POST is less specific; "here's a document that we created by filling in a web form, edit yourself appropriately". It is okay to use POST: after all, the web was catastrophically successful and we're still using POST in our form submissions.
The useful work is a side effect of these edits.
Are these RESTFul according to the REST principles?
Do they work like a web site? If they work like a web site: meaning you follow links, and send information to the server by submitting forms, or editing the webpages and submitting your changes to the server, then it is REST.
A trick though: it is normal in REST that a single method + request uri might have different useful side effects. We can have several different HTML forms that all share the same Form.action. Uploading changes to an order document might have very different effects if the edits are to the shipping address vs to the billing information or the order items.
Normal doesn't mean obligatory - if you prefer a resource model where each form request goes to a specific resource, that can be OK too. You get simpler semantics, but you support more resources, which can make caching trickier.

Rest API resources: composed for post but separate to get is ok?

I'm creating a set of RESTful API and I have this question: I have a resource that has some images attached and I'm creating my resources like this:
POST to /resource: create the object and save the images to the server.
GET to /resource returns the object but no the images, GET to /images returns the images.
My question is: is this compliant with REST or should I either make the resources completely separate or completely unified?
I choose this solution because when posting I for sure send the images, but I may need them or not when doing a get.
is this compliant with REST
It's fine - for instance, if you look at the way that Atom Publishing works, you'll see that when you post a media to a collection, two resources are created (the Media Resource and the Media Link Entry).
However, fine here means you are making tradeoffs. In particular, cache invalidation is more challenging when you a POST to one resource may change the representation of a different resource.
HTTP caching semantics are optimized for the common case, which is that a given request changes only the target resource; no spooky action at a distance.
That doesn't mean that this is the Right Way, but rather that you should understand that this is the way that HTTP makes easy, and in other cases you need to pay attention to the details.
POST can basically mean anything, and unlike PUT and GET (for which there is a bit more of a direct relation), POST is allowed to result in all kinds of side-effects, including the creation of 0 or more resources.
POST is basically the 'anything goes' method.

REST HATEOAS: How to know what to POST?

I still don't understand how the client knows what data to POST when creating a resource. Most tutorials/articles omit this and in their examples, a client always seems to know a priori what to post (i.e. using out-of-band information). Like in this example, the consumer knows that he has to place the order by setting what <drink\> he wants.
I can only image a few approaches and I don't know if they are valid:
1. Returning an empty resource
The client discovers a link to /resource with a link to /resource/create and relation "create". A GET to /resource/create returns an empty resource (all attributes are empty) and a link to /resource/create with relation "post". The client then sets values to all attributes and POSTs this to /resource/create which returns a 201 (Created). This means that the CRUD operations are not located at the resource endpoint but to URI like /resource/create and that the client might set attributes the server ignores (like a creation date which is set on the server side)
2. Returning a form
Basically the same approach as above, despite the fact that not a resource is returned but some meta-information about what fields to post and what datatypes each attributes needs to have. Like in this example. Still, the creation endpoint is not located at /resource but on /resource/create
3. Creating by updating
A POST to /resource immediatly creates an empty resource and returns a link to this resource. The client then can follow this link to update the resource with the necessary data doing PUTs.
So what is the best approach that still follows the HATEOAs paradigm and why are all of these tutorials (and even books like REST in Practice) omitting this problem?
UPDATE:
I recently found out the Sun Cloud API seems to be pretty close to an "ideal" REST HATEOAS API. It not only defines some resources and does hyperlinking between them, it also defines media types and versioning. With all this theoretical discussion, it's pretty good to have a concrete exmaple. Maybe this helps some readers of this question.
Most tutorials and books about REST are very misleading, because there are many misconceptions about REST and no authoritative source other than Fielding's dissertation itself, which is incomplete.
REST is not CRUD. A POST is not a synonym to CREATE. POST is the method to be used for any action that isn't already standardized by HTTP. If it's not standardized by HTTP, its semantics are determined by the target resource itself, and the exact behavior has to be documented by the resource media-type.
With HATEOAS, a client should not rely on out-of-band information for driving the interaction. The documentation should focus on the media-types, not on the URIs and methods. People rarely get this right because they don't use media-types properly, and instead document URI endpoints.
For instance, in your example, everything has the application/xml media-type. That's the problem. Without proper media-types, there's no way to document resource-specific semantics when everything has the same media-type without relying on URI semantics, which would break HATEOAS. Instead, a drink should have a media-type like application/vnd.mycompany.drink.v1+xml, and your API documentation for that media-type can describe what to expect when using POST with a rel link.

Is it RESTful to receive the POST Data as raw body?

If I offer a POST in my REST API, say like
https://api.myservice.com/myresource
and I want to accept a complex JSON string/object from within the POST.
Should I
omit the JSON and map the entire object to the URL (which would be quite uncool)
add the JSON Data as key => value pairs to the JSON
am I able to just access the raw body data or wouldn't that be any more restful?
When you do POST to the URL https://api.myservice.com/myresource you would be creating a myresource with the details in the POST body. The URL generally should contain your resources.
Regardless of the options you have listed I don't see any impact on any of the REST constraints. It is more valuable to ask yourself am I violating any of the REST constraints and if so, what benefits am I losing and make your decision on the relative pros and cons.
Achieving "RESTful" status should not be the end goal. Picking the constraints that are important to your application and applying them should be the goal.

Do REST API URLs have to look like this?

Is it true that to implement a RESTful API, one has to implement a URL structure that looks like this
http://example.com/post/
http://example.com/post/123
where the /123 would be used for edit, delete
Another way to ask the question is: can a URL that looks like this be called RESTful?
http://example.com/script.php?method=get_title&blogid=123
You don't have to design your URI structure like that. It could also be /some_obscure_string/base64_encoded_title/unique_id. This could also be RESTful, depending on several other factors.
But there are several best practices on how to design URIs in a RESTful web application and being as simple and as human readable as possible is one of them.
Your example http://example.com/script.php?method=get_title&blogid=123 could also be RESTful, but the query parameters indicate that some kind of RPC- or RMI-over-HTTP is used instead.
To sum it up: Don't put too much thought into your URI design. This will come automatically with a good and proper RESTful design of your application.
The Idea behind REST is that every resource has it’s own URL and you use the different HTTP methods to interact with those resources. It makes sense to define the URL structure so that the hierarchy between different resources is reflected in the URL, but you don’t have to.
If you have URLs like this
/all-posts/
/first-post
/some-stuff/second-post
/third-post
you still could provide an RESTful API to this. The Idea is that a GET to /all-posts/ returns a list of the URLs of every post object and the client uses those URLs to interact with the resources. Basically the URLs should be treated as opaque data by the client.
As long as the URL that is embedded in the client doesn’t change you also could change the structure without having to change the client.
Your example URL probably doesn’t belong to a RESTful API, since it contains a method get_title. In REST a URL represents a thing. What is to be done with the thing (should it be modified, should it contents be retrieved, ...) is not part of the URL, for that REST uses the different HTTP methods.
A key aspect of REST is that the url is the resource. a uri like
http://example.com/script.php?etc-etc-etc
doesn't put the resource identifier in the resource portion of the uri. that's not to say that a RESTful API shouldn't ever use get parameters; in fact, that's just fine:
http://example.com/posts?sort=date_asc&offset=20&limit=10
might be a great way to get the URI's of the 3rd page of oldest posts. However, using get parameters in this way should only be used in requests where the method is also GET. PUT and especially POST methods should really use simple uri's with the resource that will be affected in only the path portion.
RESTful URI design is all about resources access and they should be structured in the RESTful manner, so you should not have any query strings.
e.g. of GET
authors/
authors/1
authors/1/books
authors/1/books/10
authors/1/books/10/summary
etc.
Anything and everything is called RESTfull these days, just look at some of the responses by it's inventor Dr Roy Fielding and you'll get some ideas. It is worth doing some reading on the subject.
P.S you do not need post,get etc in your URIs, HTTP protocol is at present mostly used for consuming REST APIs and you can pass verb as a part of the call. Also there is a concept of content negotiation i.e you can request any available format from REST API (json,xml atc).
The REST concept is really based on the fact that it is URL driven, and not driven by large data-blobs. With REST, you don't have to pass a giant soap request to invoke a method - your method call/object creation/whatever you want to do is invoked simply by the URL, and the verb you used vs that URL.
Example URLs:
GET http://del.icio.us/api/
GET http://del.icio.us/api/peej/tags/
GET http://del.icio.us/api/peej/tags/test
DELETE http://del.icio.us/api/peej/bookmarks/[hash]
The structure of your URLs doesn't matter. What does matter is that each URL identifies exactly 1 resource. Each resource can have multiple URLs that point to it but each URL should only point to 1 resource.
This can be helpful. Ref:
RESTful service URLs