I have read a few articles about HATEOAS and the way that API should be implemented such that you can traverse to different states by following the links. But I'm confused as to how the client should be implemented?
From this answer:
The client knows nothing about how the server designs its URIs other
than what it can find out at runtime.
Does the client need to crawl from the root node down to a nested resource to just make a POST if it doesn't know the direct URI?
What would be the purpose of API documentation then?
For implementing HATEOAS server needs to include links to responses that goes from server to client, and client uses these links in response to communicate to server.
For eg. Client request Product list, server will respond with list of products with link to Add, edit and delete the products (if user is able to do that), which will then be transformed in client into links or buttons like Edit Product, Delete Product.
This blog might help you get more understanding.
Does the client need to crawl from the root node down to a nested resource to just make a POST if it doesn't know the direct URI?
Yes unless the root page does not contain the link which describes the POST.
What would be the purpose of API documentation then?
It describes the metadata the client can recognize for example by a link or by a property. So it describes the capabilities of the service.
To answer your first question "Does the client need to crawl from the root node down to a nested resource to just make a POST if it doesn't know the direct URI?"
The answer is No. The client always does not have to crawl from the root node. It is possible to design the URI;s such a way that the navigation to reach the direct URI can be from other views. For example if the purpose of the URI (/Products/product1/Delete) is to delete product , then it should be possible to reach this by either crawling from the /Products or by giving a namespace query of Products/Deleteview. This "DeleteView" URI should give all the URI's of the delete view. i.e it can return a uri collection like Products/product1/Delete, Products/product2/Delete etc.
To your second Question "What would be the purpose of API documentation then?"
Concept of API is a legacy of the past. Ideally the URI itself should be the documentation. This way the client can be programmed to discover and take only things that it can respond to.
We got hold of unique technology which manages these namespaces. so we are shielded from this view manipulation ourselves. I recommend using a technology to manipulate and create these URI namespaces.
Related
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.
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.
Lets consider the following flow to a RESTfull API:
API root
|
v
user list
|
v
user details
|
v
user messages
Suppose I have a client to consume the API, and I want to retrieve messages from a user with ID 42.
From what I've been studying, my client is not supposed to know how to "build" urls, and it should follow the links given by the API.
How should I do to retrieve messages for the user with ID 42?
The only way I can think is "walk" the whole API from it's root to user messages, which doesn't look very pretty or efficient to me.
Eg:
1 - GET / and get the link to the list of users
2 - GET /user/?id=42 and get the link to details of the user with the ID 42
3 - GET /user/42/ and get the link to user 42 list of messages
4 - GET /user/42/messages/ and finally get the user messages
Did I get something wrong? Is this the right way according to Roy's Fielding paper?
Or is it ok to just assume the messages url is "/user/{id}/messages/" and make the request directly?
Use URL templates in your API root. Let the client consume the API root at runtime. It should look for a URL template named something like "user-messages" with the value of "/user/{userid}/messages/". Then let the client substitute "42" for "{userid}" in the template and do a GET on the resulting URL. You can add as many of these URL templates you want for all of the required, often used, use cases.
The difference between this solution and a "classic" web API is the late binding of URLs: the client reads the API root with its templates at runtime - as opposed to compiling the client with the knowledge of the URL templates.
Take a look at the HAL media type for some information about URL templates: http://stateless.co/hal_specification.html
I wrote this piece here some time ago to explain the benefits of hypermedia: http://soabits.blogspot.dk/2013/12/selling-benefits-of-hypermedia.html
I believe what your real concern is should you go about implementing HATEOAS or not. Now as it's an integral part of REST specifications, it is recommended that each entity should have a link to it's child entity that it encompasses. In your case, API ROOT should show list of users with each "user" having a link (/root/users/{id}) to corresponding user's details. And each User details entity will contain a link to the list of "messages" (/root/users/{id}/messages) which, finally, inturn encompass the link to the actual message detail as well (/root/users/{id}/messages/{messageId}). This concept is extremely useful (and thus a part of the specifications) because the client doesn't need to know the url to where your entity is exposed. For example, if your users were on http://users.abc.com/rest/users/{id} but your messages were on http://messages.abc.com/rest/{userId}/messages/{messageId}, the user entity that encompasses the list of "messages" will already have link embedded to point to the right resource on a different server.
Now that being said, I haven't actually seen many REST implementations out there (I must admit I do not have TOO MUCH of an experience, but enough to give an opinion) where HATEOAS is being used widespread. In most cases the resources are almost always on the same server (environment) and the paths to resources are almost always relative to the root url.Thus, it doesn't make sense for the clients to parse out the embedded links from the object when they can generate one by themselves, especially when the client would like to provide access to a resource directly (View the message directly without getting the user entity provided you already know what the messageId is).
In the end, it all depends on how close do you want your REST implementations to that of specifications and what kind of clients are you going to have. My 2 cents would be: if you have time, implement REST with HATEOAS and feel proud about it :). There are libraries out there that will make this implementation (HATEOAS) somewhat transparent to you REST implementation (I believe spring has one, although not very mature. You can look at it here). If you are like me and don't have much time to go that route, I think you can continue with a normal REST implementation without HATEOAS and your clients will still be OK with it (or so I hope!)
Hope this helps!
I found this article about hacking urls: Avoid hackable URLs.
There is a very interesting discussion about the topic of this question in the comments section.
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
I would like to know if there is some best practices about the root endpoint for a REST web service? I mean, should it be a short documentation about the usage of the API itself? Should it be an XML document describing all methods available? Should it only return "unknown method"?
The question is perfectly clear to me.
I think it should respond with 404. If there is no resource associated with the root path, then there is nothing to return.
If you feel that 404 is not helpful, then it would also be OK to return the URL of the documentation.
REST is supposed to be self describing so having the root show an error is poor design in my opinion.
I like the root to contain information that allows you to navigate the rest of the API.
So for example the root might contain a link to a list of product categories from which the API user can select a category and then a list of products etc.
A self describing API means less documentation to write and keep updated!!
NerdDinner.com1
The Sun Cloud API
Twitter
Paul Jame's article
MediaWiki's API2
1. NerdDinner uses WCF Data Services, which is a great way to correctly implement RESTful services. The reason I am point to that, and not WCF data services directly is because it is a public website and you can use it.
2. MediaWiki is not a great example because they are passing actions in the URI but it is technically a RESTful service and show's a lot of interesting ideas.
This question as asked is unclear. I would guess it means something like a directory that all API methods are under. For example, the root directory of the Flickr API would be http://api.flickr.com/services/rest/.
For an example of a project that accesses the Flickr API, see python-flickrapi
the rootend point of REST API is the the API defined for the first slash i.e "/" of the url after the dispatcher-servlet. It contains all the GET for the list of resources (mostly the get for all the database tables) this list further contains all the items and in single item there will be DELETE , PUT/PATCH and SELF get URL. Thus making the implementation of HATEOS.
For me, I just redirect to my frontend.
In node JS, use res.redirect("https://<<your frontend>>");