I've been trying to implement a RESTFul architecture, but I've gotten thoroughly confused as to whether custom media-types are good or bad.
Currently my application conveys "links", using the Http Link: header. This is great, I use it with a title attribute, allowing the server to describe what on earth this 'action' actually is, especially when presented to a user.
Where I've gotten confused is whether I should specify a custom mime-type or not. For instance I have the concept of a user. It may be associated with the current resource. I'm going to make up an example and say I have an item on an auction. We may have a user "watching" it. So I would include the link
<http://someuserrelation> rel="http://myapp/watching";title="Joe Blogg", methods="GET"
In the header. If you had the ability to remove that user from watching you would get.
<http://someuserrelation> rel="http://myapp/watching";title="Joe Blogg", methods="GET,DELETE"
I'm pretty happy with this, if the client has the correct role he can remove the relationship. So I'm defining what to do with a relationship. The neat thing is say we call GET on that 'relation' resource, I redirect the client to the user resource.
What's confusing me is whether or not to use a custom mime-type. There's arguments both ways on the internet, and in my head in regards to this.
I've done a sample in which I call HEAD on an unknown url, and the server returns Content-Type: application/vnd.myapp.user. My client then decides whether it can understand this mime-type (it maintains mappings of resources it understands to views), and will either follow it, or explain that it's unable to figure out what is at the end of that link.
Is this bad?. I have to maintain special mime-types. What's particularly odd is I'm more than happy to use a standard application/user format, but can't find one specified anywhere.
I'm beginning to think I should be attempting to completely guess at rendering what in any HTTP response, almost to the point that maybe my RESTFul api should just be rendering html instead of attempting to do anything with json/xml.
I've tried searching (even Roy Fieldings blog), but can't find anything that describes how the client should deal with this sort of situation.
EDIT: the argument I have with including the custom type, is that it may not necessarily be a 'user' watching the item, it could be something with application/vnd.myapp.group. By getting the response a client knows the body has something different, and so change to a view that displays groups. But is this coupling of mime-type to view bad?.
I'd say, you definitely want to have a specific media-type for all representations. If you can find a standard one (html, jpeg, atom, etc.) use that, but if not, you should define one (or multiple ones).
The reason is: representations should be self-contained. That means your client gets a link from somewhere it should know what to do with it. How to display it, how to proceed from there, etc. For example a browser knows how to display text/html. You client should know how to display/handle application/vnd.company.user.
Also, I think you've got content negotiation backwards. You don't need to call HEAD to determine what representations the server supports. You can tell the server what your client supports in the GET/POST/etc requests using the "Accepts" header. Indeed this would be the standard way to do it. The server then responds with the 'best' representation it can give you for your accepted mime-types. You don't need more round-trips.
So, although the links you are providing can contain contextual information, usually given in the 'rel' attribute, like if the link points to a 'next page', 'previous page', 'subscribed user' or 'owner user', etc., the client can not assume any representation under those links. It knows it is semantically a 'user', so it can fill the 'Accepts' header with all supported representations for a user (application/vnd.company.user). If the representation only says text/xml, there is nothing the client can assume either of the content, or semantics of Links that it may receive.
In practice you can of course code any client to just assume what representations are under what links/urls, and you don't have to conform to REST all the time, but you do get a lot of benefits (described in Roy Fielding's paper) if you do.
Another minor point: The links do not need to contain which methods are available for a given resource, that's what OPTIONS is for. Admittedly, it is rarely implemented.
You don't have to send HTML to serve hypermedia. There are many different hypermedia formats which are much easier to parse than HTML. https://sookocheff.com/post/api/on-choosing-a-hypermedia-format/ https://stackoverflow.com/a/13063069/607033
You don't have to use a domain specific MIME type, in my opinion it is better to use a domain specific vocabulary with a general hypermedia type e.g. microformats or schema.org with JSON-LD + Hydra or ATOM/XML + microdata / RDFa, etc... There are many alternatives depending on your taste. https://en.wikipedia.org/wiki/Microdata_(HTML) http://microformats.org/ http://schema.org/ http://www.hydra-cg.com/
I am not sure whether adding the same relation to multiple methods is a good choice. Sending multiple links with different in link headers with d if you want: https://stackoverflow.com/a/25416118/607033
Related
I was wondering if it is technically RESTful to use an identifier as a grouping and not be a particular resource (no corresponding id).
For example:
get /location/address
get /location/coverage
get /location/region
These things are all a location hence having them behind the location identifier. Is this correct?
Or is it better to rethink the structure of these endpoints or break them into just /address - /coverage - /region?
First and foremost, a URI in a REST architecture is just a URI, a reference to an other resource. The actual spelling used inside the URI is furthermore not of relevance as the URI as a whole is a pointer that shouldn't get segmented or analyzed. While a set of URIs may span a whole tree of available paths to use, there is no requirement actually therefore.
An URI itself also does not necessarily tell anything about the content of the resource it points to. Fielding even 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. (Source)
This blog post further describes what Fielding meant with this statement which basically just states that proper content type negotiation should be used instead of assuming that a resource has a certain type. On the Web you might retrieve a data page of your preferred car or sports team though you will most-likely receive a page in HTML format that is generic enough and therefore widely spread that plenty of clients (browsers) support it. Through the affordance of each of the defined elements your client (browser) knows how to present these to you for more convenient access of the content.
I'm not sure about you but if I have the choice between reading some line summarizing the content of a link and having to decipher the URI itself, I definitely prefer the former one. Such metadata is usually attached to a link in some way. In HTML the anchor (<a>) tag not only ships with meta data such as href or target but also rel which basically allows to annotate a URI with a set of keywords that tell a client about the purpose of the link. Such a keywords may be something like first, last, prev or next for paging through a sub-set of a collection, or preload for telling a client that it can load the content of the referenced URI early to speed up load times as the client will most likely be interested in the content of that link next. Such keywords should be standardized to gain wider acceptance or at least base off of an extension mechanism defined in Web Linking, as Dublin Core does it i.e.
Looking at your respective URIs they already seem to express what link relation are there for. As such they could make up for good candidates for defining them as link relations such as:
http://www.acme.com/rel/address
http://www.acme.com/rel/coverage
http://www.acme.com/rel/region
A link can basically have multiple relation names assigned simultaneously, depending on the media-type the payload is exchanged for. A client that does not know what a certain link-relation means will simply ignore it, clients that however have the knowledge will act accordingly upon finding URIs with such annotations. I admit that an arbitrary client will not be able to make use of all of the link-relations out of the box, especially the extension ones, but such link-relation names might be enforced by media-types as well or support for such relation names may be added through updates or plug-ins later on.
Media types, after all, are just a human-readable description on how a payload received for such a form will look like and how it has to be processed by some automata. Hence, a generic application/json is usually a bad media-type in a REST API as it just defines that the content should be embedded between curly braces and primarily represents a key-value structure with the addition of objects and arrays, but it lacks to hint a client on what a link is or on the semantics of certain elements found within the payload. application/hal+json is an extension of the basic JSON notation and adds some processing rules and semantic definitions of certain elements such as _links or _embedded, which a client can use. Here, curies could be used a link-relations as well I guess as in the end they also end up with unique URIs as requested by the Web linking extension definition.
Certain media-types also allow to pass along further processing hints in the media-type itself through the use of profiles. As such a server could hint a client i.e. that the collection expressed by the requested resource contains entries that follow a certain logic, i.e. that the collection contains a set of orders, where a processing entity can apply additional checks upon, i.e. that certain fields must be specified or that certain inputs have to be in bound between two values and stuff.
As writing a whole new media-type is quite some effort, investigating into already defined ones is for sure a good idea. If you really think there is no media type available yet that really is applicable to your domain, you should start to write one, probably in a community effort. Keep in mind though that this media-type should be as generic as possible to allow adoption by third parties otherwise hardly any client will really support it and thus limit the number of potential peers your applications can interact with. It is further a good idea to take reference at the HTML spec to see how elements got defined and how they maintained backwards compatibility as you don't want to register a new media-type on each change.
If you just want to implement some filter mechanism to only show locations that represent addresses rather than regions you may take reference on how it is done on the Web. Here usually a server will provide you a form to select a choice among the given set of choices and upon clicking the submit button (or enter key) a request is issued to the server which will return the subset of entries matching the query. Instead of using a form a server may already provide a client with a link that is annotated, as mentioned above, with some hints a client knows that they refer to addresses, regions or whatever options you have available and can chose based on the annotated link relations the URI which is of interest to the client. Again, the actual form of the URI is not of relevance here either as a client should just use the URIs that were provided by the server.
You might ask yourself why all that is needed?! The basic answer to this question is simply to avoid breaking things when stuff changes over time. Think of a case where a client wants to retrieve details on a previously sent order. If it had the knowledge of the URI hardcoded into it and the server changes the URI style the client might not be able to retrieve this data. On the other side if it had the knowledge to look for any URI annotated with http://www.acme/rel/order and just use that URI it couldn't care less if the URI changed as it just uses the given information to send it to the mentioned endpoint. By relying on well-defined media-types and the semantics of the defined elements, any peer supporting this media-type will also be able to process it. Almost every client is able to handle HTML in some way, though hardly any generic HTTP client can really act upon a custom JSON payload format, i.e. present you a clickable link or render a nice form you can update the data of an existing resource. Custom payload makes it also difficult to reuse the same client for different endpoints. I.e. you probably wont be able to use the same client to shop on two different web-shops that expose Web-RPC-based HTTP endpoints.
So, to sum up my post, as mentioned, the form of the URI is not really of relevance in a REST architecture as a server should always provide it to the client anyway and a client shouldn't deduct the meaning from it. Instead link-relations, media-type support and content-type negotiation should be used consistently.
REST doesn't care what spellings you use for your URI, beyond the fact that they should be consistent with the production rules defined in RFC 3986.
GET /location/region
GET /region
Those are both fine.
I read that HATEOAS links are the one that separates a REST API from a normal http API. In that case, does REST need a separate name? I wonder what all this hype about REST API is about. It seems to be just a http method with one extra rule in the response.
Q) What other differences exist?
I read that HATEOAS links are the one that separates a REST API from a normal http API.
That's probably a little bit of an understatement. When Leonard Richardson (2008) described the "technology stack" of the web, he listed:
URI
HTTP
HTML
A way of exploring the latter is to consider how HTML, as a media type, differs from a text document with URI in it. To my mind, the key element is links and forms -- standardized ways of encoding into the representation the semantics of a URI (this is a link to another page, this is an embedded image, this is an embedded script, this is a form...).
Mike Admundsen, 2010:
Hypermedia Types are MIME media types that contain native hyper-linking semantics that induce application flow. For example, HTML is a hypermedia type; XML is not.
Atom Syndication/Atom Publishing is a good demonstration for defining a REST API.
Can you throw some light on what REST actually means and how it differs from normal http?
Have you noticed that websites don't normally use plain text for the representations of the information that they share? It's something of a dead end -- raw text doesn't have any hypermedia semantics built into it, so a generic client can't do anything more interesting than search for sequences that might be URI.
On the other hand, with HTML we have link semantics: we can include references to images, to style sheets, to scripts, as well as linking to other documents. We can describe forms, that allow the creation of parameterized HTTP requests.
Additionally, that means that if some relation shouldn't be used by the client, the server can easily change the representation to remove the link.
Furthermore, the use of the hypermedia representation allows the server to use a richer description of which request message should be sent by the client.
Consider, for example, Google. They can use the form to control whether search requests use GET or POST. They can remove the "I Feel Lucky" option, or arrange that it redirects to the main experience. They can embed additional information in to the fields of the form, to track what is going on. They can choose which URI targets are used in the search results, directing the client to send to Google another request which gets redirected to the actual target, with additional meta data embedded in the query parameters, all without requiring any special coordination with the client used.
For further discussion, see Leonard Richardson's slide deck from QCon 2008, or Phil Sturgeon's REST and Hypermedia in 2019.
Does n't think the client need to read the documentation if the HATEOAS link is a POST API? HATEOAS links will only guide you to an API but will not throw any light on how its request body needs to be filled....GET won't have request body. So, not much or a problem. but POST API?
Sort of - here's Fielding writing in 2008:
REST doesn’t eliminate the need for a clue. What REST does is concentrate that need for prior knowledge into readily standardizable forms.
On the web, the common use case is agents assisting human beings; the humans can resolve certain ambiguities on their own. The result is a separation of responsibilities; the humans decode the domain specific semantics of the messages, the clients determine the right way to describe an interaction as an HTTP request.
If we want to easily replace the human with a machine, then we'll need to invest extra design capital in a message schema that expresses the domain specific semantics as clearly as we express the plumbing.
To me, REST is an ideology you want to aim for if you have a system that should last for years to come which has the freedom to evolve freely without breaking stuff on parts you can't control. This is very similar to the Web where a server can't control browsers directly though browsers are able to cooperate with any changes done to Web site representations returned by the server.
I read that HATEOAS links are the one that separates a REST API from a normal http API. In that case, does REST need a separate name?
REST does basically what its name implies, it transfers the state of a resource representation. If so, we should come up with a new name for such "REST" APIs that are truly RPC in the back, to avoid confusion.
If you read through the Richardson Maturity Model (RMM) you might fall under the impression that links or hypermedia controls as Fowler named it, which are mandatory at Level 3, are the feature that separates REST from normal HTTP interaction. However, Level 3 is just not enough to reach the ultimate goal of decoupling.
Most so called "REST APIs" do put a lot of design effort into pretty URIs in a way to express meaning of the target resource to client developer. They come up with fancy documentation generated by their tooling support, such as Swagger or similar stuff, which the client developer has to follow stringent or they wont be able to interact with their API. Such APIs are RPC though. You won't be able to point the same client that interacts with API A to point to API B now and still work out of the box as they might use completely different endpoints and return different types of data for almost the same named resource endpoint. A client that is attempting to use a bit more of dynamic behavior might learn the type from parsing the endpoint and expect a URI such as .../api/users to return users, when all of a sudden now the API changed its URI structure to something like .../api/entities. What would happen now? Most of these clients would break, a clear hint that the whole interaction model doesn't follow the one outline by a REST architecture.
REST puts emphasis on link relation names that should give clients a stable way of learning the URIs intent by allowing a URI to actually change over time. A URI basically is attached to a link relation name and basically represents an affordance, something that is clear what it does. I.e. the affordance of a button could be that you can press it and something would happen as a result. Or the affordance of a light switch would be that a light goes on or off depending on the toggled state of the light switch.
Link relation names now express such an affordance and are a text-based way to represent something like a trash bin or pencil symbol next to table entry on a Web page were you might figure out that on clicking one will delete an entry from the table while the other symbol allows to edit that entry. Such link relation names should be either standardized, use widely accepted ontologies or use custom link-relation extensions as outlined by RFC 8288 (Web Linking)
It is important to note however, that a URI is just a URI which should not convey a semantic meaning to a client. This does not mean that a URI can't have a semantic meaning to the server or API, but a client should not attempt to deduce one from the URI itself. This is what the link-relation name is for, which provides the infrequently changing part of that relation. An endpoint might be referenced by multiple, different URIs, some of which might use different query parameters used for filtering. According to Fielding each of these URIs represent different resources:
The definition of resource in REST is based on a simple premise: identifiers should change as infrequently as possible. Because the Web uses embedded identifiers rather than link servers, authors need an identifier that closely matches the semantics they intend by a hypermedia reference, allowing the reference to remain static even though the result of accessing that reference may change over time. REST accomplishes this by defining a resource to be the semantics of what the author intends to identify, rather than the value corresponding to those semantics at the time the reference is created. It is then left to the author to ensure that the identifier chosen for a reference does indeed identify the intended semantics. (Source 6.2.1)
As URIs are used for caching results, they basically represent the keys used for caching the response payload. As such, it gets obvious that on adding additional query parameters to URIs used in GET requests, you end up bypassing caches as the key is not stored in the cache yet and therefore get the result of a different resource, even though it might be identical (also in response representation) as the URI without that additional parameter.
I wonder what all this hype about REST API is about. It seems to be just a http method with one extra rule in the response.
In short, this is what those self- or marketing-termed pseudo "REST APIs" do convey and many people seem to understand.
The hype for "REST" arose from the inconveniences put onto developers on interacting with other interop-solutions such as Corba, RMI or SOAP where often partly-commercial third-party libraries and frameworks had to be used in order to interact with such systems. Most languages supported HTTP both as client and server out of the box removing the requirement for external libraries or frameworks per se. In addition to that, RPC based solution usually require certain stub- or skeleton-classes to be generated first, which was usually done by the build pipeline automatically. Upon updates of the IDL, such as WSDL linking or including XSD schemata, the whole stub-generation needed to be redone and the whole code needed to looked through in order to spot whether a breaking change was added or not. Usually no obvious changelog was available which made changing or updating such stuff a pain in the ...
In those pseudo "REST" APIs plain JSON is now pretty much the de facto standard, avoiding the step of generating stub classes and the hazzle of analyzing the own code to see whether some of the forced changes had a negative impact on the system. Most of those APIs use some sort of URI based versioning allowing a developer to see based on the URI whether something breaking was introduced or not, mimicking some kind of semantic versioning.
The problem with those solution though is, that not the response representation format itself is versioned but the whole API itself leading to common issues when only a change on a part of the API should be introduced as now the whole API's version needs to be bumped. In addition to that, to URIs such as .../api/v1/users/1234 and .../api/v2/users/1234 may represent the same user and thus the same resource though are in fact different by nature as the URI is different.
Q) What other differences exist?
While REST is just an architecture model that can't force you to implement it stringent, you simply will not benefit from its properties if you ignore some of its constraints. As mentioned above, HATEOAS support is therefore not yet enough to really decouple all clients from an API and thus allow to benefit from the REST architecture.
RMM unfortunately does not talk about media types at all. A media type basically specifies how a received payload should be processed and defines the semantics and constraints of each of the elements used within that payload. I.e. if you look at text/html registered in IANA's media type registry, you can see that it points to the published specification, which always references the most recent version of HTML. HTML is designed in a way to stay backwards compatible so no special versioning stuff is required.
HTML provides, IMO, two important things:
semi-structured content
form support
The former one allows to structure data, giving certain segments or elements the possibility to express different semantics defined in the media type. I.e. a browser will handle an image differently than a div element or an article element. A crawler might favor links and content contained in an article element and ignore script and image elements completely. Based on the existence or absence of certain elements even certain processing differences may occur.
Including support for forms is a very important thing in REST actually as this is the feature which allows a server to teach a client on what a server needs as input. Most so called "REST APIs" just force a developer to go through their documentation, which might be outdated, incorrect or incomplete, and send data to a predefined endpoint according to the documentation. In case of outdated or incomplete documentation, how should a client ever be able to send data to the server? Moreover, a server might never be able to change as basically the documentation is now the truth and the API has to align with the documentation.
Unfortunately, form-support is still a bit in its infancy. Besides HTML, which provides <form>...</form>, you have a couple of JSON based form attempts such as hal-forms, halo-json (halform), Ion or hydra. None of these have yet wide library or framework support yet as some of these form representations still have not finalized their specification on how to support forms more effectively.
Other media-types, unfortunately, might not use semi-structured content or provide support for forms that teach a client on the needs of a server, though they are still valuable to REST in general. First, through Web linking link support can be added to media types that do not naturally support those. Second, the data itself does not really need to be text-based at all in order for an application to use it further. I.e. pictures an videos usually are encoded and byte based anyways still a client can present them to users.
The main point about media-types though is, as Fielding already pointed out in one of his cited blog posts, is, that representations shouldn't be confused with types. Fielding stated 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.
Jørn Wildt explained in an excellent blog post what a "typed" resource is and why a REST architecture shouldn't use such types. Basically, to sum the blog post up, a client expecting a ../api/users endpoint to return a pre-assumed data payload might break if the server adds additional, unexpected fields, renames existing fields or leave out expected fields. This coupling can be avoided by using simple content-type negotiation where a client informs a server on which capabilities the client supports and the client will chose the representation that best fits the target resource. If the server can't support the client with a representation the client supports the server should respond with a failure (or a default representation) the client might log to inform the user.
This in essence is exactly what the name REST stands for, the transfer of a resource's state representation where the representation may differ depending on the representation format defined by the selected media type. While HATEOAS may be one of the most obvious changes between REST and a non-REST based HTTP solution, this for sure is not the only factor that makes up a payload in REST. I hope I could shed some light on the decoupling intention and that a server should teach clients what the server expects through forms and that the affordance of URIs is captured by link-relation names. All these tiny aspects in sum make up REST, and you will only benefit from REST, unfortunately, if you respect all of its constraints and not only those that are either easy to obtain or what you have the mood for implementing.
In my API I should return a list of products. In the client (browser) the user can add this products to a cart, increasing, decreasing, or remove this a product from the cart.
In my response with the products list should I put the URLs actions like this:
{
"alias": 'aliasValue',
"removeUrl": 'domain/product/alias/',
"increaseUrl": 'domain/product/alias/increase/',
"decreaseUrl": 'domain/product/alias/decrease/',
...
}
Is this a good practice, I've searched for this but the only thing that I found about URL and API is about the URL structures.
What do you think?
I would advise against reinventing the wheel. There are many ways to use HATEOAS in your API.
Consider, for example, the HAL (Hypertext Application Language) approach, where you have a _links property:
{
"_links": {
"self": {
"href": "http://example.com/api/books/1"
}
},
"id": "1",
"name": "Hypermedia as First-Class Citizen"
}
What you are trying to achieve as a name HATEOAS that stands for Hypermedia as the Engine of Application State.
So if you search for it you will find a lot of formats:
JSON-LD
HAL
SIREN
ION
JSON API
Spring
Ripozo
Source: https://nordicapis.com/tools-to-make-hateoas-compliance-easier/
As REST is just a generatlization of the browsable Web we all know, you can basically apply the same concepts as if you'd implement your system for the browser. In short, a server should provide a client with all the necessary information the client will need to make educated decisions which resources to invoke next.
In a browser-based Web application the interaction model could be similar to invoking the start page, seeing a section in the response that is of interest to you, click a link to learn further details. The next page might list some items where you are provided with further controls to modify this list, i.e. add a new item, remove one and so forth. Upon clicking some "add" button a form is presented to you which teaches you what fields a request should contain and also where this request should be sent to, even if it might not be visible to you. In the back the browser will take care of that for you. The jumping point here is, the server is actually feeding the client with any information needed to proceed through his task, whether it is the choice of available links to explore or the presentation of some guidelines on how a request should look like.
In order to determine whether a link is of interest to a client a server will use meaningful link relation names "attached" to URIs a client should use instead of parsing and interpreting URIs. This allows a server to change URIs anytime without affecting a client. Fielding mentioned the following in one of his blogposts:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
In addtion to that REST APIs shouldn't have typed resources meaningful to clients as this basically couples the client tightly to the API itself and will lead to failures if the serve ever changes anything in regards to the response returned. Instead content-type negotiation should be used in order to let client and server negotiate about the actual representation format used.
A media type defines the processing rules of some payload that is received for a certain Content-Type HTTP header. These rules define both syntax as well as semantics of the document. Servers in a REST architecture are i.e. allowed to reject any messages sent for a certain content type if the rules outlined in the media type are violated.
While the focus on media-types doesn't prevent changes done to the representations received completly, it still is useful in helping to decouple clients from servers further and reduce out-of-band information needed in order to interact with the service. Instead of coupling a client directly to the API, both couple to the media-type actually, and there might be multiple media types they actually couple to. If there ever needs to be a change done to a media-type you can easily introduce a new media type or, similar to HTML, specify within the media-type how backwards compatibility is achived.
In regards to prior, out-of-band information requirements, which REST doesn't completly remove, Fielding stated
Of course the client has prior knowledge. Every protocol, every media type definition, every URI scheme, and every link relationship type constitutes prior knowledge that the client must know (or learn) in order to make use of that knowledge. REST doesn’t eliminate the need for a clue. What REST does is concentrate that need for prior knowledge into readily standardizable forms. That is the essential distinction between data-oriented and control-oriented integration. (Source)
As REST isn't a focus on one single aspect but a conglomeration of all of the aspects mentioned above, your actual question should be tackled from multiple angles.
First, either use existing link relations, i.e. administered by IANA or other microformats, define new ones which you should register with IANA at best or use some semantic web related tags like schema.org. I.e. if you have collections then next, prev, first and last are pretty meaningful (and already registered at IANA) for pagination or item for a decicated item within the list. This collection might have been returned previously as collection before or specified by the respective item in order to go back to the previous collection. If somethin like an add or edit should be done a link-relation like edit-form can teach the client that the URI will return some kind of form that will tell the client how a request to the API will need to look like.
Next, as basic JSON isn't that great in terms of providing help to a client, as all it does is define the syntactical structure of a document but lack support of given the elements meaning, some more advanced media types should be supported. As already mentioned by Cassio and Exadra37 there are a couple of JSON based document types that provide support for HATEOAS (~ URIs and link relation names). Instead of only going for i.e. application/hal+json a multitude of document types would be preferable as this just increases interoperablility with a magnitude of different clients that might come with support for other media types. Note futher that there is nothing wrong with returning a HTML representation as well. REST isn't restricting you to only specific JSON or XML content. I guess most of the time, instead of specifying an own media-type, simply using HTML would be sufficient to carry the meaning of the content from API to server.
You are of course free to create your own media type and use it. In order to increase interoperability you should however standardize it and probably also provide plugins/libraries for third party frameworks so that they are able to use your format as well.
The best advice, though, for sure is to reuse existing standards as the likelihood of other clients already being familiar with such implementations or concepts is way higher than for your custom format. Besides that, it probably also spares you from a lot of work and effort.
I'm trying to develop a RESTful api using the hypertext as an engine of application state principals.
I've settled on using the Link header (RFC5988) for all 'state transitions', it seems natural to place links there, and doesn't make my response types specific on an implementation (eg XML/json/etc all just work).
What I'm struggling with at the moment is the pagination of a collection of resources. In the past I've used the Range header to control this, so the client can send "Range: MyObjects=0-20" and get the first 20 back. It seems natural to want to include a "next" relation to indicate the next 20 items (but maybe it isn't), but I'm unsure how to do it.
Many examples include the range information as part of the URI. eg it would be
Link: <http://test.com/myitems?start=20&end=40>;rel="next"
Using the range header would I do something like the following?
Link: <http://test.com/myitems;rel="next";range="myitems=20-40"
The concern here is that the link feels non-standard. A client would have to be checking the range header to get the next items.
The other thing is, would I just leave this all as somewhat out-of-band information?. Never showing next/previous ranges (as that sort of depends on what the client is doing), and expect the client to just serialize down what it needs when it needs it?. I can use the "accepts-ranges" link hints in the initial link to the collection to let the client know its 'pageable'
eg something like
OPTIONS http://test.com
-> Link:"<http://test.com/myitems";rel="http://test.com/rels/businessconcept";accepts-ranges="myitem""
Then the client would go, oh it accepts ranges, I will only pull down the first X, and then go for the next range as necessary (this sort of feels like implicit states though).
I can seem to figure out what is really in the best spirit of HATEOAS here.
The link header spec doesn't do exactly what you want AFAIK. It has no concept of identifying client supplied parameters. The rel doc's for your link can and should specify how to apply your range implementation.
The link-template header spec https://datatracker.ietf.org/doc/html/draft-nottingham-link-template-00#page-3 does a lot of what you want, but that expired. This specified how to use https://www.rfc-editor.org/rfc/rfc6570 style templates in headers, and if you want to use headers that the direction i'd suggest.
Personally, although I agree having the links in the header abstracts you from the body's content type, i find the link header to be difficult to develop against as you can't just paste a url in a browser and see links immediately.
I've been convinced by a fellow developer (now left) that the proper way to evolve RESTful web services is by creating custom media types for your services.
For example application/vnd.acme.payroll.v1+json
This way, you can tell your client to specify the encoding to use without changing the URI.
Is this technique a good one? Usually services embed the version into the url:
eg /acme/1.0/payroll/
I've had a lot of difficulty enforcing clients to use this scheme, especially as it seems DELETE does not enforce a media type
There are a few main signaling mechanisms you can use in a RESTful service:
The media type
The rel of a resource you are linking to.
Custom headers, like Accept-Version/Api-Version.
Each of these has distinct uses, and I will outline the ways in which we have come to understand them while designing our API.
Media Types
To signal what operations are possible on a given resource, and what the semantics of these operations are, many use custom media types. In my opinion, this is not quite correct, and a rel is more accurate.
A custom media type should tell you about the type of the data, e.g. its format or the way certain information is embodied or embedded. Having a custom media type means consumers of your API are tightly coupled to that specific representation. Whereas, using something more generic like application/json says "this is just JSON data."
Usually JSON alone is not enough for a RESTful service, since it has no built-in linking or resource-embedding functionality. That is where something like HAL (application/hal+json) comes in. It is a specialization of JSON that is still a generic format, and not application-specific. But it gives just enough to overlay the linking and embedding semantics on top of JSON that is necessary for coherently expressing a RESTful API.
Link Relation Types (rels)
This brings us to rels. To me, a custom rel is a perfect way to signal what type of resource is being dealt with or linked to. For example, a custom rel for a user resource might be http://rel.myapi.com/user, which serves two purposes:
Clients of your API must know this key ahead of time, as it is API-specific knowledge. For example, if it was available on your initial resource and you were using HAL to link to the user resource, clients might find the user link via initialResource._links["http://rel.myapi.com/user"].href.
Developers writing API clients can visit that URI in their web browser, and get an explanation of what that resource represents in your API, including what methods are applicable and what they do. This is a very convenient way to communicate that API-specific knowledge I mentioned. For examples of this, see http://rel.nkstdy.co.
If you combine rels with a standard or semi-standard media type like application/hal+json, you get resources which follow a uniform format specified by their media type, with API-specific semantics defined by their rels. This gets you almost all the way there.
Custom Headers
The remaining question is versioning. How do you allow clients to negotiate different versions of the resource, while not invalidating old URIs?
Our solution, inspired by the Restify Node.js framework, is two custom headers: Accept-Version from the client, which much match X-Api-Version from the server (or Api-Version in the upcoming Restify 2.0 release, as per the new RFC 6648). If they don't match, a 400 Bad Request is the result.
I admit that custom media types are a fairly popular solution here. In my opinion they don't fit very well conceptually, in light of the above considerations, but you would not be doing something weird if you chose them as your versioning mechanism. It has some semantic issues when used with methods other than GET though, as you note.
One thing to keep in mind is that in a truly RESTful system, versioning should not be such an issue. It should only matter in one very specific situation: when the representations of your resources change in backward-incompatible ways, but you still want to keep the same rels. So if the http://rel.myapi.com/friend resource suddenly loses its username field and gains an id field, that would qualify. But if it suddenly gains a nickname field, that's not backward-incompatible, so no versioning is needed. And if the concept of "friends" is completely replaced in your API with the concept of, say, "connection", this is not actually backward-incompatible, because API consumers will simply no longer find http://rel.myapi.com/friend links anywhere in the API for them to follow.
Yes, it's a good option. It clarifies the encoding you'll be using for payloads and lets both sides negotiate a different version of the encoding without changing the URI, as you correctly pointed out.
And yes, there's no need for a client to send a DELETE along with an entity-body. I believe it will simply be ignored by a compliant HTTP server, given that no payload data is transferred in that case. The client issues a DELETE for a URI, and the server returns a response code indicating whether it succeeded. Nice and simple! If the server wishes to return some data after a DELETE then it is free to do so, and should specify the media type of the response when it does.