I am new to RESTful APIs and everywhere I read that REST APIs "must be hypertext-driven". I have googled a lot but haven't found a concrete explanation of the concept. So:
In practical terms, what does it mean that REST APIs should be 'hypertext-driven'?.
When I say hypertext, I mean the simultaneous presentation of information and controls such that the information becomes the affordance through which the user (or automaton) obtains choices and selects action. Roy T. Fielding - http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
It is about one of the fundamental constraints of REST architectural style - Hypermedia As The Engine Of Application State (HATEOAS). It means that in any given moment, client, based on hypermedia in representation of current resource, must have all the information he needs to decide where to transit next(change its Application State). That hypermedia controls in hypertext connect resources to each other, and describe their capabilities in machine-readable ways. A REST client just needs to know one thing in order to communicate with REST server - understanding of hypermedia. Opposite, in a service-oriented architecture(SOA), clients and servers interact through a fixed interface shared through documentation or an interface description language (IDL).
HATEOAS decouples client and server so that they can be developed separately.
For example,
If you make an initial call to a rest service to add a customer using some URL /customers/ then you will get a response back (consider the customer is successfully added),
HTTP/1.1 201 Created
Location: http://www.myREST/customers/<uuid>/
Now the client who made the call to add customer knows how to find the corresponding customer from the link returned as a response header.
You may ask how does client know that he can make POST to /customer/. By different means - hypermedia controls, DSL specific formats and profiles.
REST mean that api follow correct use for HTTP Verbs, Status code, etc. HTTP protocol, has verbs like: GET, POST, PUT, OPTIONS and DELETE. In a rest api, each verb is map to specific action on resource. For example:
POST is allways create a new instance of resource; GET is get the resource (or a list), DELETE is allways remove resource associated; PUT is modify/update a exist resource .....
Plus, you should use the status code for indicate response : 201 to create, 200 to modify, etc.
You can take more information on http://restinpractice.com/book/ (Jim Weber book)
Related
If I am calling a Web APi service and that service makes various other calls to other services, do I use POST or GET?
To elaborate further, let's say I call Web Api Service One saying 'Do the thing'. Web Api One's job when requested thus, is to GET data from Service Two and POST data to Service Three. Perhaps Service One will then update Service Two. Service One will then respond to caller with any success/failure.
My question again is should I the caller, use POST or GET to Service One?
It's all about the semantics of the request. From the RFC 7231:
The request method token is the primary source of request semantics;
it indicates the purpose for which the client has made this request
and what is expected by the client as a successful result.
Here's a brief description of some HTTP methods defined in the RFC RFC 7231 (click the links to check the full method definition):
GET: Transfer a current representation of the target resource.
HEAD: Same as GET, but only transfer the status line and header section.
POST: Perform resource-specific processing on the request payload.
PUT: Replace all current representations of the target resource with the request payload.
DELETE: Remove all current representations of the target resource
In addition to the methods listed above, the RFC 5789 standardized the PATCH HTTP method for performing partial updates to a resource.
POST is commonly seen as a "catch all" method, once the target resource process the request payload according to the resource's own specific semantics.
HTTP methods can be classified as safe and/or idempotent and it must be taken into account when designing an API with on the top of HTTP.
Typically I would only use a variety of HTTP verbs (GET, POST, PUT, DELETE etc) when using a REST API. Then the endpoints are resources in their own right. For example:
/car
So the verbs make sense (are you getting a car? creating one? updating one? removing one?)
But when I am not using a REST API the HTTP verbs tend to have less meaning and I generally only use HTTP POST. Otherwise you hit logical problems like you're experiencing here.
eg
/rentacar
This API models an RPC that may cause many resources to change in many ways. It is not a REST API and so the HTTP Verbs don't really relate.
But in honesty, for RPC (remote procedure calls), people choose between GET and POST by either:
GET for operations that don’t modify anything and POST for other cases.
GET for operations that don’t need too much parameters and POST for other cases.
GET and POST on a random basis or always use POST.
Purists prefer 1. But sometimes you don't know when modifications are going to occur. So, take your pick!
In RESTful websites, each resource should be identified by an URI. But how should I handle what are called "weak entities" in relational databases, aka, ressources that only make sense when related to another resource? Should these have specific URIs pointing to them too?
To give an example: Say I have a website for showing events going on in a city. Each event can have comments posted by users.
An event is a resource, with corresponding URI (/events/:id).
But should each comment have an URI, too? Like /events/:eventid/comments/:commentid ? Comments only make sense when they're associated with the corresponding event, so having a page just to represent one message seems weird/unnecessary. I only want the comments to appear on the page of the event.
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
An event is a resource, with corresponding URI (/events/:id).
But should each comment have an URI, too? Like /events/:eventid/comments/:commentid ?
If comment is a resource, it must have an identifier, but it doesn't mean that you have to support all operations for such resource. The server can return a response with the 405 status code if a method is not supported by the target resource:
6.5.5. 405 Method Not Allowed
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. [...]
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
Return a representation of the comment with the given identifier.
In RESTful websites, each resource should be identified by an URI. But how should I handle what are called "weak entities" in relational databases, aka, ressources that only make sense when related to another resource? Should these have specific URIs pointing to them too?
It depends. An important thing to recognize is that resources and entities are not one to one. You are allowed to have many resources (web pages) that include information from the same entity.
Jim Webber described the distinction this way
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation.
Domain Driven Design for Restful Systems
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
As noted by Cassio, 405 Method Not Allowed is the correct status code to use if the client erroneously sends a request with an unsupported method. OPTIONS is the appropriate mechanism for informing a client of which methods are currently supported by a resource.
You could also have it respond by redirecting the client to the /events/:eventId resource; it might even make sense to take advantage of URI Fragment support, and redirect the client to /events/:eventid#:commentid - allowing the client to use its own fragment discovery to identify the specific comment within the representation of the event.
Or, if there are useful integrations that you want to support, you could simply have this resource return a representation that exposes the integrations.
It really depends on how the client wants to work with the domain. Would an app want to get a list of all the comments for an event? Are users allowed to update their commments? Or are they anonymous comments?
If you plan to only ever use the same page to display the backend information of events and comments, then you prolly don't need a separate comments api. If you want to open the dataset to app vendors (perhaps you might want to develop an app in future) a comments api would be handy. i.e. get all comments for an event.
TutorialsPoint defines the following methods in context of RESTful design:
URI HTTP Body Result
-----------------------------------------------------------------
listUsers GET empty Show list of all the users
addUser POST JSON string Add details of new user
deleteUser DELETE JSON string Delete an existing user
:id GET empty Show details of a user
I think this is misleading, because it's not RESTful.
A RESTful design would be as following:
URI HTTP Body Result
----------------------------------------------------------------
users GET empty Show list of all the users
users POST JSON string Add details of new user
users DELETE empty Delete an existing user
users/:id GET empty Show details of a user
Is my understanding of RESTful correct?
Regardless of definition of RESTful, in my opinion, TutorialsPoint presented wrong design, because deleteUser inside URL duplicates information that is already passed as DELETE HTTP action, which violates universal principle of Once And Only Once.
The first set of endpoints is a bad design for a REST API. It's all about RPC (and DELETE requests should not have a payload).
The second set of endpoints are resource-orientated and that's what you want in a REST API. The URI identifies the resource and the HTTP method expresses the operation over the resource.
However the REST architecture goes much beyond the URIs design.
The REST architectural style is protocol independent, but it's designed over the HTTP protocol most of the time.
The fundamental concept in a RESTful application is the resource. And resources can have different representations. For more details, this answer can be helpful.
To be considered RESTful, an application must follow a set of constraints defined in the chapter 5 of Roy Thomas Fielding's dissertation:
Client-server
Stateless
Cache
Uniform interface
Resources identification
Resources representation
Self-descriptive messages
Hypermedia
Layered system
Code-on-demand
Yes your understanding is correct. That tutorial is misleading.
Lets assume we have a resource on an URL like so: foo.com/api/bar
And lets say that a user might be allowed to GET that resource, but not allowed to POST to that resource.
I can easily solve that by specifying different permissions per verb.
But how should the client know on beforhand if it is allowed to perform the POST?
Lets say we have a "save" button on a page, that should not be enabled if the user lacks the rights to do a POST.
I know about HATEOAS/Hypermedia constraint, and that I can pass a list of links for different actions together with the resource.
But AFAIK, that doesn't carry information on what verbs to use, only URL's for different actions.
Are there other variations where the verb is included?
Are there other approaches if you don't want to clutter the resource with all sorts of metadata?
This has been asked a lot on the HAL discuss forums https://groups.google.com/forum/#!forum/hal-discuss
The fact that verbs aren't returned is a decision of the hypermedia format you're using, which i'm guessing is HAL (or maybe collection+json). Some formats DO include verb information.
HAL actually allows you to include custom fields on your link objects if you wish, but i would discourage this because any standard client won't know how to interpret this.
But also i've found the verb to be worthless in the end.
First off in human 2 machine the user is going to read documentation. HAL has all of it's links dereference (via CURIE's as they are currently naemd) to human readable documentation that should describe the effects of requesting that link with different parameters, verbs, headers, etc.
Next off is that for your Application to be truly RESTful you should respond to all verbs...you might just not respond that the verb was OK. For an HTTP based app returning a 405 is VERY appropriate. Returning a 404 is not! A 500 would be worse!. Your 405 should include what methods are available for the requested resource.
Next in the case of machine 2 machine (and a bit of h2m) your application when accessed via HTTP (i try to avoid http in my answers as RESTful applications aren't necessarily HTTP..although i'd say 101% of them are) should use the OPTIONS method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) against the resource URL in order to get a description of what's possible.
Here's where i see a lot of people getting tripped up, what should the response of OPTIONS be? well what people forget is content type negotiation! The requester should say what format for option information they expect. Accept: some-machine-language/xml or application/language+json. Some RFC or standards define these content types and your API can identify what formats it supports. I would suggest you include support for text/html so that you can return human readable documentation as well about what verbs are supported. This covers the h2m scenario nicely.
The same content type negotiation can be useful when returning info about a method not being supported. The server can send a content-type that the client can understand that describes semantically what methods are allowed.
The final thing i like to point out is that methods imply client intent. i want to PUT this resource or DELETE that resource. The server should accept requests and return responses indicated what state transitions occurred because of that request. Thus it's a little silly to have the API identify possible intents of the client with every request. The client knows what it wants to do, it should try, and if it can't then it should deal with that.
HTTP Verbs are pure transport protocol verbs. Those might not be the right verbs to do application functions, precisely because of the issues you mentioned in the question. So let us see if we can approach this differently without using http verbs. Doing http verbs to do appliction actions might limit us tommorrow as we might have need to move from http to another protocol.
LEt us take an example to illustrate. Let us say we are talking about Update Delete application using HATEOAS. So in this case, if the there are two products, represented by the URL www.abc.com/product/001 and www.abc.com/product/002. In a true HATEOAS situation, If the response of the two products product/001 and product/002 has to be looked at show the client screens.
So if the response to product/001 has a response product/001/delete,product/001/change and product/002 has the response product/002/Change then the client will show delete for only product/001 and change for the other two products.
So in response to your question. By appropriately identifying actions with product now it is possible to do role based actions.
I hope i have answered your question.
I'm reasonably sure I understand the server-side of HATEOAS design - returning state URL's in the response - but I'm slightly confused about how to design a client to accept these.
For instance, we access a resource at //somehost.com/resource/1 - this provides us with the resource data and links. We'll assume POST to //somehost.com/resource is returned, indicating a 'new' action. Now I understand posting some data to that url creates a new resource, and provides a response, but where does the form to post that data reside? I've seen implementations where //somehost.com/resource/1/new provides a form which POSTS to /resource, but that URL itself contains a verb, and seems to violate REST.
I think my confusion lies in that I'm implementing a RESTful API and a client to consume it, within the same application.
Is there some sort of best-practice for this sort of thing?
I've seen implementations where //somehost.com/resource/1/new provides a form which POSTS to /resource, but that URL itself contains a verb, and seems to violate REST.
This is incorrect. A URI containing a verb does not, in itself, violate any REST constraint. It is only when that URI represents an action that this becomes a violation. If you can perform a GET request on the URL and receive some meaningful resource (such as a "create new resource" form), then that is perfectly RESTful, and good practice.
My own API is exactly as you describe: /{collection}/new returns a form. /new is just shorthand for a hypothetical /new-resource-creation-form and still represents a noun, and only supports GET requests (HEAD, OPTIONS and TRACE not withstanding).
What HATEOAS prohibits is the user agent being required to know, that in order to create a new resource, it must add /new to the name of the collection.
Basically, if you implement your API as (X)HTML, and can surf it in a browser and perform all actions (AJAX may be required for non-POST form submissions until HTML and browsers catch up with HTTP), then it complies with the hypermedia constraint of REST.
EDIT promoted from comments:
As long as the response negates any need for a priori knowledge, it conforms to the hypermedia constraint. If the client claims to understand HTML, and you send back a response containing a link to an external stylesheet or javascript (no matter where that is hosted) which the client needs to be able to render the page correctly, then it is reasonable to say that the constraint is met. The client should know how to handle all media types it claims to support. A normal human web browser is the perfect example of a client with no out-of-band knowledge about any one HTTP service (web site).
Just to say it explicitly, a web site is a kind of HTTP service. Web browsers do not treat different web sites differently. In order to search for products on Amazon, you load the Amazon service endpoint at http://amazon.com/ and follow links or fill out forms provided in that response. In order to search for products on eBay, you load the eBay service endpoint at http://ebay.com/ and do the same.
Browsers don't know in advance that for searching eBay you must do this, but for searching Amazon you have to do that. Browsers are ignorant. Clients for other HTTP services should be ignorant too.
Yes, you could provide a URI that returns a form for resource creation. Conceivably the form could be used for dynamic discovery of the elements needed to construct a new resource (but you'd want to decide how practical that would really be in a machine-to-machine environment).
Unless there is a requirement that somehow the API has an exact browser-surfable equivalent, the documentation of the media type will describe what elements are needed.
Remember that documentation of media types and the allowed HTTP verbs for a resource is not contrary to RESTful principles. Look at the SunCloud API for an example.
Indeed, according to your example, POST'ing to
//somehost.com/resource
to create a new resource is more standard than first returning a form
//somehost.com/resource/1/new
and THEN POST'ing to
//somehost.com/resource
anyway.