So, it's quite common to use content-negotiation to get a different language representation for the same resource:
GET /resource/12345 HTTP/1.1
Accept-Language: en-GB;q=9.0, fr;q=0.8, *
Accept: application/json
which would give back a representation in British, French or any other language.
{ "greeting": "Bon Jour" }
And i think this is the right way to do it, so far, i am fine with the concept of content-negotiation.
Somehow, somewhere "Bon Jour" must have been entered... now, somehow, using REST, i want to add also the British representation.
Proposal
I was tempted to introduce:
PUT /resource/12345 HTTP/1.1
Content-Language: en-GB
Content-Type: application/json
{ "greeting" : "Good Morning" }
And one could selectively delete on translation with
DELETE /resource/12345 HTTP/1.1
Content-Language: pt_BR # Portuguese Brasil
Or delete the entire resource without specifying Content-Language
However
These ways to work with multilingual versions of a resource are nowhere being described. There is nothing in the RFCs. Also, Content-Language is mostly considered as a response header, although the old RFC did call it an 'entity' header.
Request for Comments
Please feel free to comment on this proposal in using the Content-Language header field to specify in which specific language the HTTP method should be performed. Naturally, a GET does not have a content body and therefore the content language does not need to be specified.
Question
What is common / best practice, where possible avoiding to add the language in the URL?
There have been several approaches at Web authoring and handling different representations of resources, based on Content-Language as well as other content negotiation features.
One approach was Delta-V and its Variant management.
However, this was never well-enough defined to be interoperable, and was dropped from the DeltaV standard.
Another discussion was around having a PATCH body format specifically defined for modifying resource metadata. A bunch of work would have to be done to define the format and how to express how many variants should exist and how to assign content information to representations.
The gist of the repeated discussions AFAICR is that in order to do Web authoring over HTTP and support content variants would require quite a bit of work, and not just defining how to use a header on PUT/DELETE. Authoring clients would need a way to get lists of variants and how they varied.
In contrast, as you've seen with various implementations of Web servers that serve documents out of file systems or databases, implementors have come up with various non-HTTP ways of authoring language variants, some more and some less RESTful in the way browsers GET the language variants. Filesystems aren't typically capable of supporting variants without a lot of superstructure, and content negotiation doesn't seem to be a top feature of Web servers or CMS servers.
You might try searching some of the archives of IETF HTTP-related mailing lists or posting to those lists; that's where people tend to discuss the theoretical and architectural aspects of this, rather than just worrying about local implementation tradeoffs.
Related
I am currently designing an enterprise service that is purely resource oriented. After reading several blogs, books, etc. I believe REST with Hypermedia links is the way to go.
However, one thing that all these blogs and books say is to not use application/xml as the media type when using the hypermedia links in the response. None of them say why except for a generic statement like - plain URIs with no link relation type do not communicate the semantics of URIs to clients.
From what I understood, it is a recommended approach to define your own custom media type and make the client aware of how to read it. But if it is known that the clients connecting to my service will never be browsers, does it matter? Can't I just expose these links in my response with application/xml type?
I was hoping someone here can elaborate more on this.
You don't have to use custom media types. In fact REST tries to discourage people from creating overly specific media types. The ideal is that media types should convey semantic information but not be specific to any particular service.
One problem with application/xml is that it has no standard definition for what a link looks like. Is it
<Link rel="foo" href="/foo">
or is it
<foo href="/foo">
or some other variant? How can your client know how to identify what links exist in a document without using "out of band" knowledge? "Out of band" knowledge is what you want to avoid because it is what causes clients to break when servers make changes and a client cannot protect itself against changes to out of band knowledge.
The other problem with application/xml is that it contains no semantics other than a hierarchy of elements and attributes. Semantics either have to be conveyed by a media type or a link relation. If you use application/xml then you have to use link relations to tell the client how to consume that document.
There can be a nice balance between conveying semantics in link relations and media types. But to be honest, the industry is trill trying to figure out exactly what that balance is and there are lots of people with different opinions on the subject.
I would suggest looking at application/hal+xml. It is the closest thing to generic XML but with link semantics defined.
Here is the best answer I can come up with... I've recently reached out to Dr. Fielding to validate my understanding, but have yet to receive a response. Should he yell at me, I will redact it.
I suspect that, as Darrel Miller has alluded to, the goal should be to avoid creating overly specific types - after all, it has been said:
A REST API should never have “typed” resources that are significant to
the client.
I feel that most of the content of the internet regarding Hypermedia as it pertains to REST have essentially violated this principle and steers people in the wrong direction - because they introduce very specific "qualifiers" (as I will refer to them) to their resources.
You see things like application/vnd.com.foo.bar+xml or application/vnd.com.example.thing+json - some people have decided that rather than using the type itself, they will use parameters, e.g. application/xml; someKey=someValue -- this is, in my opinion, no different than qualification. This is, to me, a typed resource.
text/html is the epitome of hypertext for a reason - the browser has a processing directive that it uses to understand this media type. Not just rendering and layout, but robust interaction precedents are set by the HTML specification(s) (e.g. anchor tags cause retrieval, forms can trigger submission with encoding and so on) and it's for this reason that this very generic, highly powerful hypermedia type has allowed all the web pages we use today to come in to existence without any coupling between your browser and the server that provides them - the only thing necessary has been an understanding of what HTML, as a content-type, is.
What does this mean for APIs? It means that creating a content type specific for some resource, some specific URI (or set of them) isn't robustly using hypermedia and likely means you have the kind of client-server coupling that REST is trying to avoid. It also means that application/xml and the like are anemic - they have parsing directives but not processing directives. A well-designed REST API will have a much more generic hypermedia type, not created for a particular resource, but rather to clearly define the processing directives that potential clients must understand in order to participate.
The interesting - and admittedly probably controversial - thing is that text/html has a lot of that already - why not use it? The fact that our API consumers want something other than HTML (e.g. they think JSON or XML formats are a panacea) is really due to an inherent misunderstanding of what it means to have a hypermedia-driven application engine - namely it's that the processing directive of the representation should be rather generic. Granted, you can do this with XML, just by having your API define a clear set of elements and what they mean. The part about using HTML was just to illustrate a point.
Aspiring REST APIs, even with a rich set of hyperlinks expressing state transitions through resources, can - and it seems most often do - fall short of that extensible, long-living architectural style that REST is really about.
After having read a lot of material on REST versioning, I am thinking of versioning the calls instead of the API. For example:
http://api.mydomain.com/callfoo/v2.0/param1/param2/param3
http://api.mydomain.com/verifyfoo/v1.0/param1/param2
instead of first having
http://api.mydomain.com/v1.0/callfoo/param1/param2
http://api.mydomain.com/v1.0/verifyfoo/param1/param2
then going to
http://api.mydomain.com/v2.0/callfoo/param1/param2/param3
http://api.mydomain.com/v2.0/verifyfoo/param1/param2
The advantage I see are:
When the calls change, I do not have to rewrite my entire client - only the parts that are affected by the changed calls.
Those parts of the client that work can continue as is (we have a lot of testing hours invested to ensure both the client and the server sides are stable.)
I can use permanent or non-permanent redirects for calls that have changed.
Backward compatibility would be a breeze as I can leave older call versions as is.
Am I missing something? Please advise.
Require an HTTP header.
Version: 1
The Version header is provisionally registered in RFC 4229 and there some legitimate reasons to avoid using an X- prefix or a usage-specific URI. A more typical header was proposed by yfeldblum at https://stackoverflow.com/a/2028664:
X-API-Version: 1
In either case, if the header is missing or doesn't match what the server can deliver, send a 412 Precondition Failed response code along with the reason for the failure. This requires clients to specify the version they support every single time but enforces consistent responses between client and server. (Optionally supporting a ?version= query parameter would give clients an extra bit of flexibility.)
This approach is simple, easy to implement and standards-compliant.
Alternatives
I'm aware that some very smart, well-intentioned people have suggested URL versioning and content negotiation. Both have significant problems in certain cases and in the form that they're usually proposed.
URL Versioning
Endpoint/service URL versioning works if you control all servers and clients. Otherwise, you'll need to handle newer clients falling back to older servers, which you'll end up doing with custom HTTP headers because system administrators of server software deployed on heterogeneous servers outside of your control can do all sorts of things to screw up the URLs you think will be easy to parse if you use something like 302 Moved Temporarily.
Content Negotiation
Content negotiation via the Accept header works if you are deeply concerned about following the HTTP standard but also want to ignore what the HTTP/1.1 standard documents actually say. The proposed MIME Type you tend to see is something of the form application/vnd.example.v1+json. There are a few problems:
There are cases where the vendor extensions are actually appropriate, of course, but slightly different communication behaviors between client and server doesn't really fit the definition of a new 'media type'. Also, RFC 2616 (HTTP/1.1) reads, "Media-type values are registered with the Internet Assigned Number Authority. The media type registration process is outlined in RFC 1590. Use of non-registered media types is discouraged." I don't want to see a separate media type for every version of every software product that has a REST API.
Any subtype ranges (e.g., application/*) don't make sense. For REST APIs that return structured data to clients for processing and formatting, what good is accepting */* ?
The Accept header takes some effort to parse correctly. There's both an implied and explicit precedence that should be followed to minimize the back-and-forth required to actually do content negotiation correctly. If you're concerned about implementing this standard correctly, this is important to get right.
RFC 2616 (HTTP/1.1) describes the behavior for any client that does not include an Accept header: "If no Accept header field is present, then it is assumed that the client accepts all media types." So, for clients you don't write yourself (where you have the least control), the most correct thing to do would be to respond to requests using the newest, most prone-to-breaking-old-versions version that the server knows about. In other words, you could have not implemented versioning at all and those clients would still be breaking in exactly the same way.
Edited, 2014:
I've read a lot of the other answers and everyone's thoughtful comments; I hope I can improve on this with the benefit of a couple of years of feedback:
Don't use an 'X-' prefix. I think Accept-Version is probably more meaningful in 2014, and there are some valid concerns about the semantics of re-using Version raised in the comments. There's overlap with defined headers like Content-Version and the relative opaqueness of the URI for sure, and I try to be careful about confusing the two with variations on content negotiation, which the Version header effectively is. The third 'version' of the URL https://example.com/api/212315c2-668d-11e4-80c7-20c9d048772b is wholly different than the 'second', regardless of whether it contains data or a document.
Regarding what I said above about URL versioning (endpoints like https://example.com/v1/users, for instance) the converse probably holds more truth: if you control all servers and clients, URL/URI versioning is probably what you want. For a large-scale service that could publish a single service URL, I would go with a different endpoint for every version, like most do. My particular take is heavily influenced by the fact that the implementation as described above is most commonly deployed on lots of different servers by lots of different organizations, and, perhaps most importantly, on servers I don't control. I always want a canonical service URL, and if a site is still running the v3 version of the API, I definitely don't want a request to https://example.com/v4/ to come back with their web server's 404 Not Found page (or even worse, 200 OK that returns their homepage as 500k of HTML over cellular data back to an iPhone app.)
If you want very simple /client/ implementations (and wider adoption), it's very hard to argue that requiring a custom header in the HTTP request is as simple for client authors as GET-ting a vanilla URL. (Although authentication often requires your token or credentials to be passed in the headers, anyway. Using Version or Accept-Version as a secret handshake along with an actual secret handshake fits pretty well.)
Content negotiation using the Accept header is good for getting different MIME types for the same content (e.g., XML vs. JSON vs. Adobe PDF), but not defined for versions of those things (Dublin Core 1.1 vs. JSONP vs. PDF/A). If you want to support the Accept header because it's important to respect industry standards, then you won't want a made-up MIME Type interfering with the media type negotiation you might need to use in your requests. A bespoke API version header is guaranteed not to interfere with the heavily-used, oft-cited Accept, whereas conflating them into the same usage will just be confusing for both server and client. That said, namespacing what you expect into a named profile per 2013's RFC6906 is preferable to a separate header for lots of reasons. This is pretty clever, and I think people should seriously consider this approach.
Adding a header for every request is one particular downside to working within a stateless protocol.
Malicious proxy servers can do almost anything to destroy HTTP requests and responses. They shouldn't, and while I don't talk about the Cache-Control or Vary headers in this context, all service creators should carefully consider how their content is consumed in lots of different environments.
This is a matter of opinion; here's mine, along with the motivation behind the opinion.
include the version in the URL.
For those who say, it belongs in the HTTP header, I say: maybe. But putting in the URL is the accepted way to do it according to the early leaders in the field. (Google, yahoo, twitter, and more). This is what developers expect and doing what developers expect, in other words acting in accordance with the principle of least astonishment, is probably a good idea. It absolutely does not make it "harder for clients to upgrade". If the change in URL somehow represents an obstacle to the developer of a consuming application, as suggested in a different answer here, that developer needs to be fired.
Skip the minor version
There are plenty of integers. You're not gonna run out. You don't need the decimal in there. Any change from 1.0 to 1.1 of your API shouldn't break existing clients anyway. So just use the natural numbers. If you like to use separation to imply larger changes, you can start at v100 and do v200 and so on, but even there I think YAGNI and it's overkill.
Put the version leftmost in the URI
Presumably there are going to be multiple resources in your model. They all need to be versioned in synchrony. You can't have people using v1 of resource X, and v2 of resource Y. It's going to break something. If you try to support that it will create a maintenance nightmare as you add versions, and there's no value add for the developer anyway. So, http://api.mydomain.com/v1/Resource/12345 , where Resource is the type of resource, and 12345 gets replaced by the resource id.
You didn't ask, but...
Omit verbs from your URL path
REST is resource oriented. You have things like "CallFoo" in your URL path, which looks suspiciously like a verb, and unlike a noun. This is wrong. Use the Force, Luke. Use the verbs that are part of REST: GET PUT POST DELETE and so on. If you want to get the verification on a resource, then do GET http://domain/v1/Foo/12345/verification. If you want to update it, do POST /v1/Foo/12345.
Put optional params as a query param or payload
The optional params should not be in the URL path (before the first question mark) unless you are suggesting that those optional params constitute a self-standing resource. So, POST /v1/Foo/12345?action=partialUpdate¶m1=123¶m2=abc.
Don't do either of those things, because they push the version into the URI structure, and that's going to have downsides for your client applications. It will make it harder for them to upgrade to take advantage of new features in your application.
Instead, you should version your media types, not your URIs. This will give you maximum flexibility and evolutionary ability. For more information, see this answer I gave to another question.
I like using the profile media type parameter:
application/json; profile="http://www.myapp.com/schema/entity/v1"
More Info:
https://www.rfc-editor.org/rfc/rfc6906
http://buzzword.org.uk/2009/draft-inkster-profile-parameter-00.html
It depends on what you call versions in your API, if you call versions to different representations (xml, json, etc) of the entities then you should use the accept headers or a custom header. That is the way http is designed for working with representations. It is RESTful because if I call the same resource at the same time but requesting different representations, the returned entities will have exactly the same information and property structure but with different format, this kind of versioning is cosmetic.
In the other hand if you understand 'versions' as changes in entity structure, for example adding a field 'age' to the 'user' entity. Then you should approach this from a resource perspective which is in my opinion the RESTful approach. As described by Roy Fielding in his disseration ...a REST resource is a mapping from an identifier to a set of entities... Therefore makes sense that when changing the structure of an entity you need to have a proper resource that points to that version. This kind of versioning is structural.
I made a similar comment in: http://codebetter.com/howarddierking/2012/11/09/versioning-restful-services/
When working with url versioning the version should come later and not earlier in the url:
GET/DELETE/PUT onlinemall.com/grocery-store/customer/v1/{id}
POST onlinemall.com/grocery-store/customer/v1
Another way of doing that in a cleaner way but which could be problematic when implementing:
GET/DELETE/PUT onlinemall.com/grocery-store/customer.v1/{id}
POST onlinemall.com/grocery-store/customer.v1
Doing it this way allows the client to request specifically the resource they want which maps to the entity they need. Without having to mess with headers and custom media types which is really problematic when implementing in a production environment.
Also having the url late in the url allows the clients to have more granularity when choosing specifically the resources they want, even at method level.
But the most important thing from a developer perspective, you don't need to maintain the whole mappings (paths) for every version to all the resources and methods. Which is very valuable when you have lot of sub-resources (embedded resources).
From an implementation perspective having it at the level of resource is really easy to implement, for example if using Jersey/JAX-RS:
#Path("/customer")
public class CustomerResource {
...
#GET
#Path("/v{version}/{id}")
public IDto getCustomer(#PathParam("version") String version, #PathParam("id") String id) {
return locateVersion(version, customerService.findCustomer(id));
}
...
#POST
#Path("/v1")
#Consumes(MediaType.APPLICATION_JSON)
public IDto insertCustomerV1(CustomerV1Dto customer) {
return customerService.createCustomer(customer);
}
#POST
#Path("/v2")
#Consumes(MediaType.APPLICATION_JSON)
public IDto insertCustomerV2(CustomerV2Dto customer) {
return customerService.createCustomer(customer);
}
...
}
IDto is just an interface for returning a polymorphic object, CustomerV1 and CustomerV2 implement that interface.
Facebook does verisoning in the url. I feel url versioning is cleaner and easier to maintain as well in the real world.
.Net makes it super easy to do versioning this way:
[HttpPost]
[Route("{version}/someCall/{id}")]
public HttpResponseMessage someCall(string version, int id))
I was doing some reading on REST this morning and I came across the HATEOAS principle ("hypermedia as the engine of application state").
Quoting the REST Wikipedia page:
Clients make state transitions only through actions that are dynamically identified within hypermedia by the server (e.g. by hyperlinks within hypertext). Except for simple fixed entry points to the application, a client does not assume that any particular actions will be available for any particular resources beyond those described in representations previously received from the server.
And Roy Fielding's blog:
...if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period.
I read this as: The client may only request state changes based on the actions made available from the body of the response from the server (the hypertext).
In an HTML world, this makes perfect sense. The client should only be able to request state changes (new actions/pages) based on the links made available to them through the hypertext (HTML).
When the resource is represented in other ways - such as JSON, XML, YAML etc. This is not so apparent.
Let's take an example "REST" JSON API:
I create a new resource (a new comment for example) by sending a POST request to
/comments.json? # with params...
The server responds with:
# Headers
HTTP/1.1 201 Created
Location: http://example.com/comments/3
Content-Type: application/json; charset=utf-8
... Etc.
# Body
{"id":3,"name":"Bodacious","body":"An awesome comment","post_id":"1"}
I know that I can now access this comment at the URI returned in the header: http://example.com/comments/3.json
When I visit http://example.com/comments/3.json I see:
{"id":3,"name":"Bodacious","body":"An awesome comment","post_id":"1"}
Suppose the API's documentation tells me that I can delete this comment by sending a DELETE request to the same URI. This is fairly common amongst "REST" APIs.
However:
The response from the server at GET http://example.com/comments/3.json doesn't tell me anything about being able to delete the comment by sending a DELETE request. All it shows me is the resource.
That I can also DELETE a comment with the same URL is something the client knows through out-of-band information (the documentation) and is not discovered and driven by the response from the server.
Here, the client is assuming that the DELETE action (and possible others) are available for this resource and this information has not been previously received from the server.
Have I misunderstood HATEOAS or am I right in saying than an API matching the above description would not, in the strict sense, be a REST API?
I'm aware 100% adherence to REST is not always possible or the most pragmatic way to go. I've posted this question purely to satisfy my own curiosity about the theory behind REST, not for advice on real world best-practice.
Jon Moore gave an excellent talk in Nov 2010 about the nuts and bolts of writing a truly RESTful (i.e. HATEOAS supporting) API and client. In the first part, he suggests the JSON is not a proper media type for REST because it lacks a commonly understood way of representing links and supported HTTP methods. He argues that good ol' XHTML is actually perfect for this since tools for parsing it (i.e. XPath) are readily available, it supports forms (think GET link templating and PUT, POST, and DELETE methods) and has a well-understood way of identifying hyperlinks, plus some other advantages mainly achieved through the ability to use the API with any standard web browser (eases the jobs for devs, QA, and support staff.)
The argument I'd always made prior to watching his talk is that JSON is so much lower of bandwidth consumer than any *ML language e.g. XML, HTML, XHTML. But by using terse XHTML where possible such as relative links instead of absolute ones (hinted at but not so evident in the example he uses throughout his talk), and by using gzip compression, this argument loses a lot of weight.
I realize efforts such as JSON-Schema and other RFC's are underway to try standardizing things in JSON, but in the meantime, Moore's talk convinced me to give XHTML a try.
JSON as a hypermedia type doesn't define an identifier for application flow. HTML has link and form tag that that guide a user through a process.
If your application is only concerned with PUT, POST, DELETE, GET on a resource, your documentation could easily explain that.
However, if it were more complicated like adding a rebuttal to a comment and that rebuttal was a different resource then the comment you would need hypermedia type that would guide the consumer create the rebuttal.
You could use HTML/XHTML, Create your own 'bodacious+json' or use something else. Here are all the different media types
http://www.iana.org/assignments/media-types/index.html
I'm using HAL and it has a pretty active group. Here are links to it.
http://www.iana.org/assignments/media-types/application/vnd.hal+json
http://stateless.co/hal_specification.html
The book "Building Hypermedia APIs with HTML5 and Node" goes deep into hypermedia and media types. It shows how to create a media type for a specific or general purpose in XML or JSON.
A RESTful solution would be to utilise the Allow-header to inform the client of the available methods/actions:
> GET /posts/1/comments/1 HTTP/1.1
> Content-Type: application/json
>
< HTTP/1.1 200 OK
< Allow: HEAD, GET, DELETE
< Content-Type: application/json
<
< {
< "name": "Bodacious",
< "body": "An awesome comment",
< "id": "1",
< "uri": "/posts/1/comments/1"
< }
Fielding's dissertation sets out two types of metadata: representation metadata; and resource metadata.
The Allow-header in HTTP/1.1 functions as resource metadata because it describes some property of a resource; i.e. the methods it allows.
By fully utilising the features provided by HTTP you eliminate the need for any out-of-bound information, and become more RESTful.
HATEOAS in a simple HTTP context describes how a client can navigate from one representation to another by following URIs using GET, whilst the Allow-header informs the client of the additional methods supported by the resource that generated the representation.
It's a neat design; the client asked for a representation, and additionally received a whole bunch of extra metadata about the resource that enables the efficient requesting of further representations.
I think the quote you have from the Wikipedia REST page is somewhat misleading in its choice of words and hasn't helped here (N.B. It has been improved since this question was asked).
All HTTP clients have to assume that a GET-method is likely to be available for the majority of resources. They do this because support for GET and HEAD are the minimum requirements for an HTTP/1.1 server. Without this assumption the web would not function. If a client can assume GET is available, then why not make other assumptions about common methods such as DELETE, or POST?
REST and HTTP aim to leverage the power of making assumptions about a basic set of methods in order to reduce the overall volume of requests on a network; if a request succeeds there's no need for further communication; but if a request fails with status '405 Method Not Allowed', then the client is immediately in receipt of the requests that could succeed via the Allow-header:
> ANNIHILATE /posts/1/comments/1 HTTP/1.1
> Content-Type: application/json
>
< HTTP/1.1 405 Method Not Allowed
< Allow: HEAD, GET, DELETE
< Content-Type: application/json
<
If the basic set of HTTP/1.1 methods aren't enough then you are free to define your own. However, it would be RESTful to solve problems using the available features of HTTP before defining new methods or putting metadata into the message-body.
A fully discoverable JSON API that doesn't require any out-of-band knowledge as you put it so succinctly:
"That I can also DELETE a comment with the same URL is something the client knows through out-of-band information (the documentation) and is not discovered and driven by the response from the server."
...is completely possible. It just requires a simple standard and a client that understands the standard. Check out hm-json and the hm-json Browser project:
https://bitbucket.org/ratfactor/hm-json-browser/
As you can see in the demo, absolutely no out-of-band documentation is needed - only one entry point URI from which all other resources and their HTTP methods can be discovered by browsing.
By the way, HAL as mentioned in suing's answer is very, very close to your hypothetical requirements for HATEOAS. It's a great standard and it has a lot of cool ideas like embedded resources, but it has no way of informing the client about all available HTTP methods such as DELETE for a given resource.
Another solid (and new as of May 2013) attempt at resolving HATEOAS for JSON can be found here:
JSON API: http://jsonapi.org/
The premise of your question contains an often misunderstood aspect of REST – that the API response body entity be responsible for not only communicating the representational state of the requested resource but for also communicating the over-all state of the application the resource belongs to. These two things - resource state and application state are not the same thing.
The response entity body by definition provides you the state of the resource at a point in time. But a single resource is only one of many that comprises an application. Application state is the combined states of all in scope related resources – at any point in time – from the perspective of the application consumer - human or machine. To deliver this 'application state' a level 3 REST API make possible HATEOAS.
Since Hypertext is what most people mean when referring to the 'Hyper'media in HATEOAS, the special power of hypertext is it's ability to link to other media. Further, since most experience hypertext via HTTP/HTML this tends to lead many to think hyperlinks are only possible via an anchor tag or link tag within the body of a response entity - but this is not so.
If the transport protocol is HTTP then application state can and should be communicated via headers. Specifically, one or more 'Link' HEADERS with a 'rel' attribute to provide semantics. The Link HEADER along with the ALLOW header are the HTTP mechanisms for communicating what the next possible state transitions are and how to go about accessing them.
If you decide to not use these built-in mechanisms than your options are to try and communicate the application state by 'piggy-backing' on your resource state communication channel i.e. the response body, which leads to trying to devise some form of additional specification into the design of the resource itself.
When this is done - 'piggy-backing'- many run into content-type issues because the response body has to be specified by a MIME/Content-type like XML or JSON which means figuring out how to implement the HATEOAS mechanisms via some custom content-type specific format like custom XML tags or key:value pairs of nested object. You can do this, many do - e.g. see json-api suggestion above, but again HTTP already provides mechanisms for this.
I think it goes to us as humans always thinking we have to see or be able to click on these links as in the normal web use-case but we are talking about APIs that I can only assume are being built not for human consumption but for machine consumption - right? The fact that headers - which are there by the way as part of the response - are not visible in most human interfaces to HTTP i.e. browsers is not an issue with REST but rather an implementation limitation of the HTTP Agents on the market.
Hope this helps. BTW if you want a good human browser for APIs google 'Paw API Browser'
Based on info in the following question REST Content-Type: Should it be based on extension or Accept header?, I'm aware either custom URIs or specifying Accept Headers are 'acceptable' (pun intended) methods for for a REST-ish web service to determine response format for the client.
However, a lot of big names seem to use the custom URI method with their APIs. What are the strengths of one way over the other?
In REST, URIs are intended to identify only a resource. Content negotiation is used to identify representation format. It's your traditional separation of concerns. When using the URI to identify the representation format you are mixing those concerns.
In addition to mixing concerns, my observation is that when using the URI based approach people generally know the convention and rely on URI building rather than hypertext to navigate. This increases coupling and can cause problems if the server ever wants to change the URI structure.
With that being said, there are some positives from the URI approach, namely convenience. During development, you can launch the browser and easily see what the server is responding with by simply entering it in the address bar ('example.com/foo.json'). When relying 100% on content negotiation it's a bit more difficult, and you have to rely on plugins or cURL, anything that can manipulate the headers.
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).