I'm developing a REST API and I have a question about resource representations.
Suppose I have the "person" resource under the /app/person/{id} URI. I need an XML representation, that basically is all the object fields as XML nodes under the root. Now, requirements indicate that we must also support another kind of XML representation enforced by a proprietary schema.
My question: is it in accordance with REST best practices to support a proprietary content type like text/my-type for the same resource? Note that both are XML but formatted differently, and most importantly they don't carry the same information (e.g. one representation may include other fields like modified-since).
Important! - I know that being pragmatic and keeping it simple is more important than guides and "best practices" but I just wanted to know if this is the way to go under a RESTful architecture.
If the second format is simply a different syntax (or can reasonably be viewed as such), it's perfectly fine (and RESTful and in compliance with REST best practices) to add it as a second representation with another media type. If you consider the difference to be more than syntactical, you should probably create a different resource. The same is true if you want to be able to link to a specific representation (because it needs a different URI if you want to do so). In this latter case, you might want to consider a canonical, format-independent resource as well that can return a 303 See Other with links to the specific ones.
Yes and no. There are no REST constraints that prevent you from returning two different representations of a resource from the same URL. Even, if one media type is a proprietary format. Be careful about allowing the content to vary too much, I hear that some people get pretty upset about that.
Also, for the custom formats you should use a media type under the vendor subtree
e.g. application/vnd.companyname.format+xml
However, it is not really in the spirit of REST to return proprietary formats. That being said, you can do with without any problems other than limiting serendipitous re-use.
Content Negotiation is built into HTTP using the Accept and Accept-Encoding headers. The client apps should specify what type they want returned by setting these headers.
If these are just two different representations of a Person resource, then you ought to have two media types for them. If at all possible try to find and reuse standard representations and their media types (see http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven). Both media types should have the form application/type+xml (and see Darrel's comment).
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'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.
This is a follow up on a question asking for an explanation of REST.
As you can see from the comments to my answer, we've had a small argument with Darrel Miller on the best media representation of the resources. We've had a further email discussion that resulted in this question.
The main difference between Darrel's and mine understanding of REST is whether the semantic of the data is part of the REST API.
Darrel believes (my interpretation of his words :-)) that the semantic of the data is an essential part of the REST API and as such, the media representation choosen should reflect it. Thus, a proper REST API should choose either:
a well-known media like ATOM to represent the data, so that as many clients could understand the semantic of the resource natively;
an app-specific media type like application/vdn.mycomany.mymedia and expect the client to understand this media type to be able to consume the resources data.
Application/xml is not a good resource representation, as it does not represent the semantic in the media type, yet requires the client to know more about the semantic.
I, on the other hand, believe that the REST API is a separate layer from the actual data representation. The media type exposed by the API is just a container to transfer the resource data. The actual semantic of the data is treated separately. Thus, a client that does not understand the data, can still consume the REST API. Application/xml is a really good data representation, as it allows tight coupling for clients that understand the schema, yet still allows client that don't understand the schema to do some basic processing of the resources.
Thus, the question: is the data semantic part of the REST API? Should we choose only media types for resources representation that actually represent the semantic of the data as well?
I would appreaciate if people post in their answers some citations, preferably from the Roy man himself. :-)
Let's start at the beginning: media types are there to provide the client with a format it can use to decide what to do next. Without an html page, the browser has no links to go to. Without an html renderer, the browser cannot render a page and won't know what to do.
Without a media type, the client has no clue if it will be able to do anything with the byte stream. Indeed, when a client receives the headers specifying application/xml, it has no knowledge of what to do beyond get an xml parser.
So the question really is, should the client be able to make a decision based on the http message without having a look inside the message, or should it go and peek inside the message (or worse, parse the message first) to know what to do.
Lack of media types means that your client will have to do additional peeking work, or worse process the entity body itself, before it can make a decision, be it for rendering or for processing. You now have to add a lot of custom behavior for each of your formats you may want to process, and you loose a bit of coupling in the process.
It's also an http fundamental that intermediaries should be able to process the requests without inspecting the body, and there as well application/xml is problematic.
Now when you say that the semantic of the media types is part or not of the API... What constitutes the API?
From a client perspective, there is no API. There is an initial representation that lets the client make a decision as to what to do next. The media type is indeed where the client gets the information it requires to navigate the "API", and as such there can be no API without representations.
Furthermore, a client should have only three bits of knowledge: a bootstrap location, the HTTP protocol and the media types. The first is only a URI and doesn't convey much beyond the location of a represetnation needed to continue. The second has already very clear semantics. The third is the one where you have control, as it's the contract you have with your client.
That contraact says that whenever you want to do something, the something will have semantics: to add a customer, send a application/vnd.acme.customer+xml to /customers using a POST.
Hence my answer: designing a REST architecture relies on two steps: resource modeling (at the conceptual level) and media type building. Anything else and you're likely doing it wrong.
I don't see the need to be overly pedantic about it. A resource can expose multiple representations; each with its own semantics (and even multiple dimensions of semantics at that). If one representation doesn't provide the semantics required by a particular use case, expose one that does.
Thus, a client that does not
understand the data, can still consume
the REST API.
I'm not sure that's a good litmus test for what does or does not make a decent representation. What good is a client that can consume a document but not understand it well enough to do anything with it? I guess I don't understand how "basic processing of resources" makes application/xml a better choice than some arbitrary blob of 1s and 0s?
Since you asked for references, here's an article from Roy Fielding where he "proposes" a bitmap representation of social network graphs. I can certainly get a machine to display these bitmaps, but of what use is that if I don't understand the underlying social network graph? Would changing the representation to application/xml allow a naive client to extract additional meaning from it that isn't contained in the bitmap? Nope.
Check out this set of slides from Mark Baker for more explanation as to why application/xml does not satisfy the "self-describing" constraint. You can also read a number of posts on his blog including this one where he continues to explain why application/xml + namespace is not equivalent to media-types.