Could REST API OPTIONS be used as the HATEOAS only request? - api

As I've understood it, REST MUST use the HATEOAS constraint to be implemented properly. My understanding of HATEOAS is that basically every resource should share information about what communication options it has and how the consumer can use those options to achieve their end goal.
My question is if the HTTP OPTIONS method could be used as a way to navigate a REST API. Basically the response from an OPTIONS request would include the possible actions to take on a resource which would make it possible to consume the API without knowing the endpoints.
e.g.
An initial request to the API
HTTP OPTIONS /api
Could return all resources available for consumption and their relations. Like a massive tree to consume the API and all it has to offer. This idea doesn't neglect implementing HATEOAS on other responses as well, but the OPTIONS request would allow navigation without returning data that the consumer might not actually want to consume.
Is this a really bad idea? Or is it something that is commonly implemented. I'm currently attempting to implement a REST API but I'm having a hard time understanding the benefit of HATEOAS if there is no way to navigate the API without actually requesting data that you might not necessarily need when consuming certain end points. And I assume HATEOAS aims to make clients consume resources by their relation and not actually hard coding the end point?
TL;DR
Could HTTP OPTIONS request act as a way to navigate a REST API by returning what communication options are available for the requested resource without actually returning the resource?

According to RFC 7231
The OPTIONS HTTP method requests information about the communication options available for the target resource, at either the origin server or an intervening intermediary. This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action.
...
A server generating a successful response to OPTIONS SHOULD send any header fields that might indicate optional features implemented by the server and applicable to the target resource (e.g., Allow), including potential extensions not defined by this specification. The response payload, if any, might also describe the communication options in a machine or human-readable representation. A standard format for such a representation is not defined by this specification, but might be defined by future extensions to HTTP. A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in the response.
So, basically a response to an OPTIONS request will tell your client which HTTP operations may be performed on a certain resource. It is furthermore admissible to target the whole server on utilizing * instead of a specific resource URI.
A response to an OPTIONS request may look like this:
HTTP/1.1 204 No Content
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Expires: Thu, 20 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
x-ec-custom-error: 1
which states that a certain resource supports the mentioned operations in the Allow header of the resonse. Via the Cache-Control header a client knows that it by default can cache responses of safe requests (GET and HEAD) for up to 7 days (value is mentioned in seconds). The x-ec-custom-error header specifies a non-standard header that is specific to a particular software, in that particular case to a ECS Server. According to this Q & A the meaning isn't publicly documented and therefore application specific.
In regards to returning a tree of traversable resources from the given resource the OPTIONS operation was requested for, technically this could be possible, however, certain systems might produce an almost never-ending list of URIs. Therefore such a design is questionable for larger systems.
My understanding of HATEOAS is that basically every resource should share information about what communication options it has and how the consumer can use those options to achieve their end goal.
Hypertext as the engine of application state (HATEOAS) is basically just a requirement to use the interaction model used on the Web for decades quite successfully and offer the same functionality to applications. This enabled applications to surf the Web similar like we humans do.
Great, but how does it work?
On the Web we use links and Web forms all the time. Through a Web form a server is able to teach a client basically what properties a certain resource supports or expects. But that's not all! The same form also tells your client where to send the request to (target URI), the HTTP method to use and, usually implicitly given, the media type the payload needs to be serialized to upon sending the request to the server. This, in essence, makes out-of-band API documentation unnecessary as all the information a client needs to make a valid request is given by the server already.
On a typical Web site you might have a table of entries which offers the option to add new entries, update or delete existing ones. Usually such links are hidden behind fancy images, i.e. a dustbin for deleting an entry and a pencil for editing an existing entry or the like where the image represents an affordance. The affordance of certain elements make it clear what you should do with it or what's the purpose of that element. A button on a page wants to be pushed while a slider widget wants to be changed while a text field waits for user input. As applications aren't that eager to work on images a further concept is used instead. Link relation names exactly serve this purpose. I.e. if you have a pageable collection consisting of multiple page à 25 entries i.e. you might be familiar with a widget containing arrows to page through that collection. A link here should usually be annotated with link relation names such as self, next, prev, first or last. The purpose of such links is quite clear, some others like prefetch, that indicates that a resource can be loaded in the background early as it is very likely that the next action may request it, might be less intuitive at first. Such link relation names should be standardized or at least follow the Web Linking extension mechanism.
Through the help of link-relation names a client that knows to look for URIs annotated with next i.e. will still work if the server decides to change its URI scheme as it treats the URI rather opaque.
Of course, both client and server need to support the same media type that furthermore is able to represent such capabilities. Plain application/json is i.e. not able to provide such a support. HAL JSON or JSON Hyper-Schema at least add support for links and link relation names to JSON based documents, while hal-forms, halo+json (halform) and ion might be used to teach a client how a request needs to be created. The question here shouldn't be which media type to support but how many different ones you want to support as the more media types your API is able to handle, the more likely it will be to interact with arbitrary clients not under your control.
These concepts allow you to basically use the controls given in the server response to "drive your workflow" forward. In essence, what you, as an API designer should do is to design the interactions of a client with your API so that it follows a certain, as Jim Webber termed it, domain application protocol or state machine as Asbjørn Ulsberg put it that basically guides a client through its task, i.e. ordering from your shop API.
So, in short, HATEOAS is comparable to Web surfing for applications by making use of named link relations and form-like media type representations that allow you to take actions solely on the response retrieved from a server directly instead of having to bake external knowledge stemming from some reference documentation page (Swagger, OpenAPI or the like) into your application.
But how does HATEOAS benefit the consumer in practice then?
First, it does not have to consult any external documentation other maybe than the current media type specification, though usually support for well-known media types is already backed into popular frameworks or at least allows to add support through plugins or further libraries. Once the media type is understood and supported interactions with all serivces that also support the same media type is possible, regardless of their domain. This allows to reuse the same client implementation to interact with service A and service B out of the box. In an RPC-like systems you'd need to integrate the API of service A first and if you want to interact with service B also you need to integrate those API separately. It's most likely that these APIs are incompatible and thus don't allow the reusage of the same classes.
Without knowing the URL for a resource, is the idea that the consumer can discover it by browsing the API, but they will still have a hard dependency on the actual URL? Or is HATEOAS purpose to leverage actions on a certain resource, i.e. the consumer knows the users end-point but he does not need to know the end-points for actions to take on the users resource cause those are provided by the API?
A client usually does not care about the URI itself, it cares about the content a URI may provide. Compare this to your typical browsing behavior. Do you prefer a meaningful text that summarizes that links content so you can decide whether to request that resource or do you prefer parsing and dissecting a URI to learn what it might do? Minifying or obfuscating URIs will do you no favor in the latter case though.
A further danger arise from URIs and resources that a client put meaning to. A slopy developer will interpret such URIs/resources and implement a tiny hack to interact with that service assuming the URI/resource will remain static. I.e. it is not unreasonable to consider a URI /api/users/1 to return some user related data and based on the response format a tiny Java class is written that expects to receive a field for username and one for email i.e.. If the server now decides to add additional data or rename its fields, the client suddenly will not be able to interact with that service further. And rest assured that in practice, especially in the EDI domain, you will have to interact with clients that are not meant to interact with the Web or where programmers implemented their own JSON framework that can't coope with changing orders of elements or can't handle additional optional fields, even though the spec contains notes on those issues. Fielding claimed that
A REST API should never have “typed” resources that are significant to the client. Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client. The only types that are significant to a client are the current representation’s media type and standardized relation names. [ditto] (Source)
Instead of typed resources content type negotiation should be used to support interoperability of different stackholders in the network.
As such, the URI itself is just the identifier of a resource that is mainly used to learn where to send a request to. Through the help of meaningful link relation names a client should know that it is interested in i.e. http:/www.acme.com/rel/orders if it wants to send an order to the service and just looks up the URI that either is annotated with that Web Linking extension realtion name or that has an URI attached to it. Whether the link relation name is just an annotation (i.e. a further attribute on the URI element) or the URI being attached to the link-relation name (i.e. as an embedded object of the link relation name) is dependent on the actual media type. This way, if a server ever decides to change its URI scheme or move around resources, for whatever reason, the client will still be able to find the URI that way and it couldn't care less about the characters present in the URI or not. It just treats the URI as opaque thing. The nice thing here is, that a URI can be annotated with multiple link relation names simultaneously, which allows a server to "offer" that URI to clients that support different link-relation names. In the case of forms the URI to send the request to is probably contained in the action attribute of the form element or the like.
As you hopefully can see, with HATEOAS there is no need for a hard dependency on URIs, if so there may be a dependency on the link-relation name though. It still requires URIs to learn where to send the request to, but through looking up the URI via its accompanying link relation name you make the handling of URIs much more dynamic as it allows a server to change the URI anytime it wants to or has to.

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.

Which kind of information can be collect about "website third parties"?

I have collected all the requests made by websites with the aim to identify the third-parties through the requests which are made by a website. I used selenium and WebDriver to do that.
These requests can be made by the JavaScript present in the source code of the website or can be dynamically called by the web-page from the advertisements or can be initiated by Google or DoubleClick or Facebook. These requests help to track the data that is being shared by these websites with or without the user consent.
You can see an example of the requests when the browser wants to load this website: www.focuscamera.com/ in this excel file:
https://drive.google.com/file/d/16wNA0dFUehrjPww31TAIj8GZUZ05LsIU/view?usp=sharing
My questions are:
1- which kind of HTTP header field can be used for my analysis if I tend to gather some info about third parties? my goal is to distinguish and differentiate the third party behavior!
For example, the field content-length in the requests indicates the size of the entity-body. So a request with higher content-length means that the third party received and collect more data/information?
2- What does exactly content-length indicates? what does exactly "HTTP request body data" contain?
3- Are there any other HTTP header fields that I can use if I aim to distinguish and differentiate the third party behavior? ( a list of field I collect can be found in sheet1 of the excel file I shared before)
4- Are there any other information on the internet that I can use if I aim to distinguish and differentiate the third party behavior? For example, I use cookiepedia.co.uk in order to know what kind of services third parties provide? is it functionality, performance, or Targeting/advertising?
It sounds like you may be reinventing the wheel here. Take a look at https://webbkoll.dataskydd.net; they provide lots of security and privacy analysis on any site you like. Generate nice visual request maps using https://requestmap.webperf.tools:
Try using that tool on sites like wired.com and forbes.com to see how spectacularly bad it can get!
To answer your questions specifically:
Headers are not massively useful as they are within each request (it's the request itself that's more interesting), but the important ones from a privacy perspective will be Referer and Set-cookie. Content-length does indeed tell you how big the request body is – that will always be 0 on a GET request and so is usually omitted – large post requests indicate more data is being transmitted, but that may be down to inefficiency rather than anything else.
Content-length indicates the length of the data (in bytes) within the body of a POST request. An HTTP request body can contain any kind of data: text, images, video, audio, formatted data.
There are some, but most headers are functional rather than semantic, concerned with making the request actually work. It's more interesting that requests happen at all than what they contain.
You can't necessarily tell what kind of service a third party is providing from the requests themselves, but the domains they are going to are more interesting. For example anything going to doubleclick.com is going to be ad and tracking related because of what that domain is known to be used for (Webbkoll cites these as "known trackers"); So you're correct that sites like cookiepedia can help you find out what a particular service does. The divisions between functional/performance/profiling are mostly made up by ad companies to excuse their behaviour, and you can't tell what they are using data for, only whether they are receiving data, and what data they are receiving (because you can see what's in the requests they make using browser developer tools). To clarify - a site could receive your full name and address, but do absolutely nothing with it; but you can't tell that from looking at the data that's sent. In privacy terms, it's always best to assume the worst (because ad companies absolutely cannot be trusted!), so if they are receiving data, assume it will be abused.

RESTful Response when the POST request results in the creation of different kind of resources?

I have been working on designing an API that lets client create a product (think of product as something like website domain, something that comes into existence when client makes order for it to the service). Correspondingly with every purchase results in creation of the order object. Which means creation of two resources via a single POST request.
So afaik, the RFC standards recommends sending 201 on resource creation with URI for the resource in the Location header. But in the above scenario, we are creating two resources, domains and orders and I would want response to contain information related to both the resources.
Response would look something similar to this
POST /domains/
Request
body: {"domain_name": "awesome.com"},
Response
Body: {"order_id": "1234"}
Headers:
Location: http://example.com/awesome.com
But does not look very RESTful. I was wondering if there was a RESTful way to do this?
RFC 7231, section 6.3.2
The 201 (Created) status code indicates that the request has been fulfilled and has resulted in one or more new resources being created. The primary resource created by the request is identified by either a Location header field in the response or, if no Location field is received, by the effective request URI.
The 201 response payload typically describes and links to the resource(s) created.
In other words, on the web we would solve your riddle by returning an HTML document that includes hyperlinks to all of the created resources, along with text to describe each, so that the client would know which new identifiers are available.
To make such a response machine readable, we would do the work of documenting the schema of the message, so that specialized clients would know how to identify the semantics of each of the provided links.
The same idea works if you replace HTML with a different media type (for example application/json). You define the schema, and then specialized clients can parse the response to find the identifiers that they need.
Of course, REST is largely about standardizing things so that we can use general purpose components; application/json is somewhat inadequate here, as it doesn't include a URI type (just strings, which are too general). So to be more "RESTful", you would choose one of the specialized JSON types that has a general purpose representation of a link.
Sookocheff's article On Choosing a Hypermedia Type.... is a decent starting point for the kinds of questions you will want to be considering.

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.

Consuming a REST API endpoint from a resource ID

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.