--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft.
For more options, visit https://groups.google.com/groups/opt_out.
Thanks Mike, that post does say basically everything I'm trying to say.
With an API, the whole point is to get the humans out of that loop, or as nearly so as possible. There's a human developer involved in creating the initial app, of course, and there may even be a human developer on call if things go south. But if I impose an incompatible change via API, my users (who are programs) begin failing, and my customers (who employ that on-call developer) lose money, and my employer gets an angry call. Bad blood all around. It's poor consolation at best if the new requirement is well documented, or even self-evident to a human: by the time the human returns to the loop, problems have already occurred.
I've seen hypermedia advocates claim to have this problem solved, but I've never seen the claim made convincing--indeed, I'm never quite sure they're actually solving the problem I just presented.
On Jun 17, 2013, at 6:41 PM, Steve Klabnik <st...@steveklabnik.com> wrote:Well, I assert the opposite. I give HTML and the WWW as my evidence.
HTML has been backwards compatible for a looooong damn time, and is in
production in quite a few places, I hear.
A common metaphoric inference, but flawed. HTML and WWW are successful, yes, but that's because they always have a human in the loop.
...
I've seen hypermedia advocates claim to have this problem solved, but I've never seen the claim made convincing--indeed, I'm never quite sure they're actually solving the problem I just presented.
I agree, and disagree at the same time. :)
I agree that presenting HTML as the archetype for a successful hypermedia system is a flawed metaphor because of fact it's designed to have a human sit in the middle.And for most of the time I've been studying REST (since 2006) I've agreed with your entire thesis that "to make something client code can follow the requisite client complexity grows without bounds" and so on these hypermedia lists I've felt like the little kid who keep telling the emperor he had no clothes.But after much recent studying of Roy's comments here[1] I've achieved an epiphany about hypermedia, if you can call a very gradual understanding "an epiphany" and this is where I disagree (and think/hope you'll agree once I explain.)Most of the "elaborate meta-architectures" you describe appear to be trying to create a *single media type* designed to be used for hypermedia and infuse with meta with the apparent goal of enabling fully automated processing for any arbitrary use-case. And the focus on the lists I follow have been on hypermedia to the exclusion of other factors (or so it seems from the outside looking in.)However, my understanding of Roy's comments tell me that the proper approach to REST is not to create an uber-type capable of being the be-all, end-all of hypermedia but instead to create a small number of use-case specific media types that enable client agents to be built that have in-built knowledge of the media types.For example, consider an "application/invoice" media type that is as simple as early HTML, with XML-like elements that designate things like "item" and "billto" and "shipto" and that embed URLs where appropriate. If such a media type existed and was in use by enough users to gain critical mass then this media type could be the API equivalent for invoices that text/html is for human navigable hypertext documents and then many could/would build clients that are fully aware of "application/invoice." (This is the part where I disagreed.)However this hasn't happened. Why? Having every individual mint a new media type for ever new project is not the answer because the benefit only really accrues when there is a large number of systems that can process the media type exist, either via one processing library used by many, or many different processing libraries also collectively used by many.In order to get critical mass you need most to agree on the use of the same media type for similar use-cases but in the case of something like "application/invoice" most of those who might use it and drive adoption are competitors. And without the lack of an external catalyst driving a consolidation towards a standard competitors rarely collaborate to converge. As such as have ongoing chaos much like the integration chaos that existing pre-commercial web in the "client-server" days.What will it take to change it? An entity like the W3C or an individual with enough clout could convene a group to be the external catalyst to identify major use-cases and drive consolidation to a standard (Who? Roy could do it, but it's obviously not his focus/interest.) Or related organizations like Apigee and their competitors could get together to drive it since they are not competing on things like invoice processing are not their core strategy but having exponential API usage growth would benefit them all.Or it might simply take a lot more time in evolution where many developers try to do it better until a one or more hit on successes that gain traction and enough take notice to drive change.Or in the worst case, no change ever occurs because no entity or person (is able to or wants to) drive this change and no developers hit on broad success in anything they try.Me, I'd really like to see the first option happen because it would mean seeing useful results sooner than later. But what is actually going to happen is anybody's guess.BTW, how this relates to versioning is that an "application/invoice" media type would really need to be evolved in backward compatible ways as HTML has (mostly) been evolved.
The takeaway for me is that versioning is basically an insurance policy - the goal is to never have to call upon it, but when you need it, you really really need it, and you can't introduce it "just in time" - it's got to be there from the get-go (even as you hope that it's never needed).
+1
Any time i can introduce change into a distributed system w/o breaking clients, that's what i do. i _rarely_ find i MUST break clients in order to support the change i need to make. for that reason, i rarely find using the version pattern useful.
+1
But after much recent studying of Roy's comments here[1] I've achieved an epiphany about hypermedia, if you can call a very gradual understanding "an epiphany" and this is where I disagree (and think/hope you'll agree once I explain.)
What will it take to change it? An entity like the W3C or an individual with enough clout could convene a group to be the external catalyst to identify major use-cases and drive consolidation to a standard (Who? Roy could do it, but it's obviously not his focus/interest.) Or related organizations like Apigee and their competitors could get together to drive it since they are not competing on things like invoice processing are not their core strategy but having exponential API usage growth would benefit them all.
BTW, how this relates to versioning is that an "application/invoice" media type would really need to be evolved in backward compatible ways as HTML has (mostly) been evolved.
Well, whatever else happens, I can heartily thank you for clarifying Roy's thoughts on this. I've spent the time, but I can't say I've had the epiphany (slow or otherwise)!
If I helped, I'm glad I was able to. It was certainly not easily groked with the available information, that's for sure.
I've rather gone off standards bodies, lately, but I am rather excited by this one gleam in the dark: there's an Internet Draft proposal to standardize the form of problem-report replies, anyway:
Yes, I saw that. Frankly I've come to assume that whatever Mark Nottingham comes up with, it's going to be good.
BTW, how this relates to versioning is that an "application/invoice" media type would really need to be evolved in backward compatible ways as HTML has (mostly) been evolved.Did I miss something, or did you just say "Don't Do That"? ;-)
Let me clarify. Ideally, it would be backward compatible. In the real world, I don't have a good solution for when it can't be.
IOW, I'm taking a pass. :)
-Mike
For example, consider an "application/invoice" media type that is as simple as early HTML, with XML-like elements that designate things like "item" and "billto" and "shipto" and that embed URLs where appropriate. If such a media type existed and was in use by enough users to gain critical mass then this media type could be the API equivalent for invoices that text/html is for human navigable hypertext documents and then many could/would build clients that are fully aware of "application/invoice." (This is the part where I disagreed.)However this hasn't happened. Why? Having every individual mint a new media type for ever new project is not the answer because the benefit only really accrues when there is a large number of systems that can process the media type exist, either via one processing library used by many, or many different processing libraries also collectively used by many.
I guess most of the successful media type like for example image/jpeg, image/png, text/vcard, text/calendar are read-only (immutable) media-types. I don't see the application/invoice media-type being immutable.Is there some pattern here as to why certain media-types are accepted more readily than others?
I guess most of the successful media type like for example image/jpeg, image/png, text/vcard, text/calendar are read-only (immutable) media-types. I don't see the application/invoice media-type being immutable.
I don't understand the use of the word "immutable" in this context. Elaborate?
Is there some pattern here as to why certain media-types are accepted more readily than others?
"Accepted" how, and by whom?
-Mike
Well, these examples suggest a pattern: if Someone Else, for their own purposes, has already cast some media type in stone (in the real, non-REST world, that is), then the REST media type can be likewise stoney.
Exactly.
I really don't see the "application/invoice" having that compelling and extensive a collaboration requirement. Invoice-collaboration happens, but it's one-on-one.
-MikeInvoice was simply an arbitrary example.But then I don't see why it couldn't be compelling. For example, if there were such an media type I could see someone recording time using Harvest and Harvest could generate an "application/invoice" that gets posted to another company's Xero accounting system, as one of many different ways it could be used.So why not?
But then I don't see why it couldn't be compelling. For example, if there were such an media type I could see someone recording time using Harvest and Harvest could generate an "application/invoice" that gets posted to another company's Xero accounting system, as one of many different ways it could be used.So why not?
Because everyone's invoicing has idiosyncratic requirements:
The same is also true for document markup, yet HTML emerged and flourished.The way to handle the special cases is to allow non-standard embedded data for those who need special cases and then, over time, the standard could evolve to address common use-cases that were not initially recognized as common.
Either this standard invoice has every feature needed by anyone (which would be impractically unwieldy),
Agree, that would be awful.
or it's extensible (but the extensions still have the same problem), or it evolves as new circumstances arise (i.e., it's not immutable).
-MikeEvolution does not require backward incompatibility though. With reasonably intelligent up-front design it should not be too hard to to maintain backward compatibility, in most cases.And if they screw it use, there can always the version number stored in the media type, worst case. (Not ideal, I admit.)
But then I don't see why it couldn't be compelling. For example, if there were such an media type I could see someone recording time using Harvest and Harvest could generate an "application/invoice" that gets posted to another company's Xero accounting system, as one of many different ways it could be used.
Because everyone's invoicing has idiosyncratic requirements:The same is also true for document markup, yet HTML emerged and flourished.
Is the invoice for T&M or fixed price work? Are the payment terms net-30, net-45 or something else? How are travel expenses split out? What about tax, foreign currency transactions?? etc. etc. ad nauseamMy point is that while "file" data such as images are simple (there are only so many "sensible" ways images can be represented), structured data is full of all sorts of variances, exceptions, corner cases, assumptions, arbitrary "rules", regulatory restrictions, company-specific policies etc. etc. that makes standardisation unlikely to succeed.Who here remembers EDI? More importantly, who here is using or implementing EDI X12 document types today? I can only recall running into EDI once, and that was back in the 90s - to my mind that speaks a lot to the practical difficulties of standardising business data structures.
That concern applies for (practically) every standard that has and will ever exist.The solution is to do the 20% that happens 80% of the time in the standard and allow the special cases to be handled by embedded data. Then, as time progresses the standard is evolved to include the 20% of the remaining 80% that is used 20% of the time. And so on.EDI was a nightmare because it did many things badly compared with what we know today to be best practices for large scale long lived interoperable systems. In a nutshell, EDI didn't follow REST. :)
Have I missed something? HTML is a language for describing documents, but I'm not aware of any standard for specific document formats-- "this is how you make a home page, any nonconforming page may not be served at your http://host/ URL". Unthinkable!
Of course not. Just like you wouldn't need a different media type to describe different types of invoices.
We already have several languages for defining REST payload documents (XMLSchema, JSON Schema, HAL, and so forth). These are better analogies to HTML. Indeed, the strongest REST-world analogue to HTML would really be XML or JSON. None of that's particularly in question in this thread. What I thought we were talking about is "using one of those languages to define a canonical form for particular document types, such as application/invoice."
Yes to the latter.Your point about the former means that I didn't explain what I was trying to explain well enough because you are taking it in a direction I didn't intend nor envision.
I've seen a lot of invoices on the web, all written in HTML, but none of them in the least "standard."
I have no idea how you arrived on that from what I wrote, but again it was probably my inability to explain well enough.
Evolution does not require backward incompatibility though.
I have no idea how you arrived on that from what I wrote, but again it was probably my inability to explain well enough.
Reading through this thread, I'm not convinced that a version number actually solves the problem either.
So… may be we need a real example that Jack or Mike could provide.
If you re-read you'll see hidden in all the other words that I punted on having a solution for backward in-compatible changes for a media type. I don't know what to do there.
I think this defines the crux of the philosophical difference exposed in this thread - do you believe that hypermedia provides a way to transform what would otherwise be backwards-compatibility-breaking changes to be backwards compatible, or not?
One thing to consider is that an API's services are not a media type nor vice-versa. I introduced the concept of the media type to this thread (possibly off-topic) when Jack mentioned he didn't see how hypermedia actually solved the problem without creating bigger ones (I'm paraphrasing and if I got it wrong, Jack I apologize.)So I can envision that an API's services are likely more fragile than a media type might be and more in need of versioning. But that's just my hypothesis at this point.
Speaking for myself, I still haven't seen any convincing evidence that hypermedia provides this. I'm not even sure that I believe that it's possible in theory (whether via hypermedia or some other yet-to-be-invented mechanism).
To be clear, that's what I believed until very recently, and only recently have I started to believe I finally understand what Roy was saying about hypermedia so many years ago. Is it a panacea? No. But I think it does provide guidance for circumstances where it can apply; for media types used broadly.
What I do believe is that such changes will be required of any non-trivial, long-lived app that exposes an API, and that not having an a priori mechanism for dealing with that situation will result in #epicfail. ... but in reality there's little up front cost in establishing a versioning mechanism - most of the cost is only incurred if/when a new version becomes necessary (which you're working equally hard to avoid in both cases anyway).
Yep, pretty much agree.
I have no idea how you arrived on that from what I wrote, but again it was probably my inability to explain well enough.
* The question was asked, "what's the best strategy for versioning an API?"
....
* You rejoined "Sure you can, as illustrated by the fact that HTML works."
Ah I see the confusion, and it was completely my fault. I read your post that talked about hypermedia not working well because of the necessary complexity and I replied to say that I (recently came to) believe that it does work assuming you are using a widely known media type that is specific to the use-case. Of course that hasn't occurred much beyond HTML, RSS, ATOM, etc.So, I effectively hijacked the thread (sorry) to discuss hypermedia. I actually took a pass on versioning which was the question the thread and I now realize you were focused on. My comments on versioning were limited to implying via mnot's link that versioning is important but should be rarely used, and regarding the versioning of media types for backward incompatible changes, the only answer I have is "Don't do it." (not great, I know.)
If it's a certain type of breaking change, then the old version might be immediately DOA anyway. Then what?
I suppose it preserves the root url for when you've really decided that your current efforts have no future, i.e.vs
So what does a version number mean?Things change all the time and it's no big deal, but every now and then, oops, move to v2?If it's a certain type of breaking change, then the old version might be immediately DOA anyway. Then what?
Right. So why do we need to bake in versioning at the beginning as a "get out of jail free card" when, some unknown time in the future, we can just tell everyone to use blue.api.example.com?
And you have a policy of infrequent changes then the next obvious version is here:
But nothing says you can't do this if it makes you happier:
-Mike
Note: I'm not arguing that hypermedia backwards compatibility is some silver bullet. I'm just not convinced that version numbers add any additional positive value over the negative value they introduce (e.g. big bang upgrades for clients).
You can't build a serious m2m API without some form of versioning strategy. Automated clients have to couple to some set of things in your application, and those things will eventually need to be changed in a breaking way... such is the nature of automated clients and application-things. It has to be dealt with.
There isn't really anything about REST or hypermedia which prevents you from employing a versioning strategy.
Where hypermedia can help is in providing the basis for developing a flexible, granular versioning strategy.
I'll describe what this might look like with HAL, because that's what I know:
In a HAL based API your clients transition over links, those links are selected (primarily) by their link relation. A link relation is itself a URL which should point to some description document that tells developers what to expect from the resource at the other end of the link (what methods, headers, properties, etc). This means that your application and its documentation has a natural granularity to it (i.e. broken down by link relations).
This can then form the basis of your strategy: which is not to version by media type or URL prefix, but to do it using link relations.
So if the behaviour for a given link changes in a non-breaking way (e.g. an additional _optional_ parameter is allowed in a POST request) then the link relation document can be updated accordingly and everything still works fine (because the change was non breaking).
And if the behaviour of a given link needs to change in a breaking way, then a new link relation should be created. This new link relation can run in parallel to the old one for as long as necessary , and in hal it can be marked as deprecated (which should cause a compliant hal client to log a warning that its traversing a link that's being deprecated).
The overall effect of this kind of strategy is that you can manage change in your API on a granular basis (i.e. per link) which enables a more gradual evolution of the API over time through small changes instead of in big releases. This is easier to manage and carries lower risk. Its the same ideas underlying lean, agile, continuous delivery, etc.
So I don't think versioning is unnecessary but I do think that there are better ways of doing it than URL prefixes or media types.
The alternative doesn't have to be "over-architected" either, provided we don't get carried away with kitchen sink hypermedia designs that are unnecessarily complicated.
I would like to think hal+json is a good start.. There's almost 300 people in hal-discuss and a tonne of libraries for it now so I guess it must be in the right ball park! :)
Cheers,
M
In the case where we really just have to break backwards compatibility, how are version numbers superior to any other solution? Old clients are dead if they don't upgrade "in time".
Originally I has intended to use a date for hal's deprecation property but instead opted for a URL value which can then offer more detail about about the deprecation (including but not limited to the due date). I'm not sure the date on its own is hugely actionable information for a client library, so I prefer this approach.
http://tools.ietf.org/html/draft-kelly-json-hal-05#section-5.4
Any good?
--
In the case where we really just have to break backwards compatibility, how are version numbers superior to any other solution? Old clients are dead if they don't upgrade "in time".
The reasons why I'd opt for a new hostname in this scenario have little to do with API design.1. The important changes have time to mature to mostly bug-free.2. The cutover becomes an ops change, which in this case feels like less of a risk than a development change.3. Less people have to work on the weekend, and the team is happier.
We are creating a REST API that will be used by many consumers. For version, we decided to use Accept header. Consumer sends requested version in Accept header (application/json,version=1.0). As part of first API, we introduced 30 resources, all tagged as version 1.0Now we putting standards on how the version-ing of API will work1) If we change in any resource which is transparent to consumer, we call that minor version. Consumer will still send the same version (say 1.0) which internally will be routed to correct version of resource. When I say correct version of resource, I meant that we maintain a technical version for each resource and at the entry point, we map incoming API version to technical version. So consumer will still send the request with 1.0 which will be internally routed to 1.x technical version of the resource.2) If a change is not transparent to consumer, we call that major change. In this case consumer has to send the new decided version with request.Here the problem comes...Say we had 30 resources, all tagged as 1.0. We changed 2 resources which considered as major change, for that we asked consumer to send the new version, lets say 2.0But all other 28 resources are not changed. But because now consumer has moved to new major version of API (2.0), the unchanged resource should respond with 2.0 as well.(Imp point to note here that consumer always rely on one major version. It's not possible that consumer send 1.0 for few resources and 2.0 for few others. If consumer moves to 2.0, all resources under the API should respond with 2.0)To respond unchanged 28 resources work with 2.0, we are considering 2 options1) Create copy for all 28 resources. That way we will have separate implementation for all resources comes under 2.0. It require lot of efforts everytime and go against the re-usability principal2) Reuse existing ones. At the entry we decide that if incoming is 2.0 and matches the URI of unchanged resource, route to existing one.which you guys think is good to go with? Any other approach/suggestion?ThanksRohit
The problem that you're facing is you created a new media type (specifically, a specialization of an existing media type) even though, when specializing the type, you probably wanted 30 different media types, so you can distinguish one media type from another in the headers, without needing to examine the URI.
Here's an approach I have been considering for a while, and that's in a context like Rohit described: Create one new media type i.e. "application/vnd.examplecorp.v1+json" and then to design it so that it can address all 30 different use-cases.If you look at HTML, it works the same way. HTML can have a list of images, or it can have a document with headings and paragraphs; it all depends on which elements to use; the combinations are almost infinite.So rather than this:application/json;profile="http://example.com/v1/item"Why not this:application/vnd.examplecorp.v1+jsonAnd then have the file contain an "item" as the root property of the element? i.e.:Other instances of the same media type could start like this:{ "item": {...} }
{ "person": {...} }{ "people": {...} }{ "orders": {...} }{ "items": {...} }etc.
JSON can have optional properties so why not define a media type for an entire problem domain instead of one specific use-case in that problem domain?Granted, I've not proven this concept yet so it may have flaws, but from studying the main example given as a working example of hypermedia it seems there is precedent for it...
Here's an approach I have been considering for a while, and that's in a context like Rohit described: Create one new media type i.e. "application/vnd.examplecorp.v1+json" and then to design it so that it can address all 30 different use-cases.
If you look at HTML, it works the same way. HTML can have a list of images, or it can have a document with headings and paragraphs; it all depends on which elements to use; the combinations are almost infinite.
So rather than this:application/json;profile="http://example.com/v1/item"
Why not this:application/vnd.examplecorp.v1+json
And then have the file contain an "item" as the root property of the element? i.e.:{ "item": {...} }Other instances of the same media type could start like this:{ "person": {...} }JSON can have optional properties so why not define a media type for an entire problem domain instead of one specific use-case in that problem domain?
{ "people": {...} }
{ "orders": {...} }
{ "items": {...} }
etc.
Granted, I've not proven this concept yet so it may have flaws, but from studying the main example given as a working example of hypermedia it seems there is precedent for it...-Mike
Right, that's pretty much my first suggestion. While it works as a solution, I don't prefer it: it adds coupling (generic user agents won't understand the media type) and
If I'm not mistaken, Roy Fielding argues for REST against generic media types that can be understood by generic user agents. My interpretation of his post and comments[1] are that he advocates for user agents that have in-built understanding of the media type and that everything needed for the client to know how to process it is found in the media type definition and he also argues that the number of media types should be small.Of course if you are arguing for an architecture that is explicitly not REST then please ignore the preceding paragraph.
forces you to look at the entity body (while not outright wrong, it is more costly than just looking at the Content-Type header, you're essentially sending a response no different than a multipart/form-data response).
Forces you for what purpose? Can you describe a use-case where this is going to be a big concern? Has it been a big issue with HTML? And if you are going to process the body why is it an issue to have to look into the body?From Roy[1]:
REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution. Many of the constraints are directly opposed to short-term efficiency.
Are you more concerned about short-term efficiency? Which is valid if you are, but its not REST.
Additionally, I just like URIs.
I like them too, but only when they are called URLs. :)OTOH URLs are not needed for everything, especially when they add unnecessarily recurring complexity. For example, who can remember the full valid URLs for the different HTML 4 DOCTYPE declarations? I sure as hell have never been able to. Fortunately sanity prevailed with "<!DOCTYPE HTML>" for HTML 5.
It says that there's a globally unique name for the particular vocabulary deployed in the JSON, which allows you to talk about your particular format at the same time you talk about third party JSON formats. The more specific you can get in distinguishing the media types, the better.
If you define a specific media type and register it with IANA you get to distinguish the media type exactly. And even if you don't register it you can include a link to documentation as an X-{header} or in the body or if you like.
And you can serve a JSON Schema at that URI and clients can use to extract hyperlinks from the JSON, and humans can read it to see descriptions and labels. All around it's just far friendlier to generic user agents, or people writing API mash-ups.
Use of JSON Schema, while viable creates so much complexity that I question the wisdom of building an architecture that requires it. I don't think HTML would have been successful enough to for the web to explode in usage if HTML was a meta document. XML is like HTML+meta and while XML is widely used for Enterprise use-cases it requires a order of magnitude more skill to work with it when it starts including namespaces and that means fewer people can work with it.I'm arguing the same is true if you have to use JSON Schema with JSON. Great for Enterprise applications where they can afford perfection and are not concerned with the scale of decades but not so good at following Postel's law which IMO is an significant reason of why the web has worked.But, YMMV of course. :)
If I'm not mistaken, Roy Fielding argues for REST against generic media types that can be understood by generic user agents. My interpretation of his post and comments[1] are that he advocates for user agents that have in-built understanding of the media type and that everything needed for the client to know how to process it is found in the media type definition and he also argues that the number of media types should be small.Of course if you are arguing for an architecture that is explicitly not REST then please ignore the preceding paragraph.
Forces you for what purpose? Can you describe a use-case where this is going to be a big concern? Has it been a big issue with HTML? And if you are going to process the body why is it an issue to have to look into the body?forces you to look at the entity body (while not outright wrong, it is more costly than just looking at the Content-Type header, you're essentially sending a response no different than a multipart/form-data response).
From Roy[1]:REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution. Many of the constraints are directly opposed to short-term efficiency.
Are you more concerned about short-term efficiency? Which is valid if you are, but its not REST.
I like them too, but only when they are called URLs. :)Additionally, I just like URIs.OTOH URLs are not needed for everything, especially when they add unnecessarily recurring complexity. For example, who can remember the full valid URLs for the different HTML 4 DOCTYPE declarations? I sure as hell have never been able to. Fortunately sanity prevailed with "<!DOCTYPE HTML>" for HTML 5.
If you define a specific media type and register it with IANA you get to distinguish the media type exactly. And even if you don't register it you can include a link to documentation as an X-{header} or in the body or if you like.
Use of JSON Schema, while viable creates so much complexity that I question the wisdom of building an architecture that requires it. I don't think HTML would have been successful enough to for the web to explode in usage if HTML was a meta document. XML is like HTML+meta and while XML is widely used for Enterprise use-cases it requires a order of magnitude more skill to work with it when it starts including namespaces and that means fewer people can work with it.
A generic media type is one that any user agent can use, e.g. HTML, or JSON. Inventing your own media type, e.g. application/vnd.examplecorp+json, introduces coupling (an interface specific to your API) which is very not-RESTful and something that Roy argues against in that blog post. Requiring specialized knowledge specific to your API is what is bad.
A media type of e.g. application/json;profile=http://example.com/v1/post.json is generic so that a robot or other user agent can make use of the endpoint, while at the same time indicating which vocabulary it uses so that it may be used in an RPC fashion. That is to say, it properly identifies that the content being returned is a subset of application/json, and so the user agent knows it can apply application/json behavior, as well as whatever other behavior it knows is specific to the specified profile, if any.
I've read and re-read Roy's post and comments so many times that I'm 99% sure that the above is actually contrary to what is RESTful (oh how I wish Roy was on this list so he could explain what he meant instead of me trying my best in earnest.)But it took a long time for me to develop my current understanding; I previously thought Roy meant as you explained. But I was left with inconsistencies and my current understanding resolves those inconsistencies. Let's see if I can quote Roy[1] in order of his post to clarify (any emphasis mine):
Roy: A REST API should not contain any changes to the communication protocols aside from filling-out or fixing the details of underspecified bits of standard protocols, such as HTTP’s PATCH method or Link header field. Workarounds for broken implementations (such as those browsers stupid enough to believe that HTML defines HTTP’s method set) should be defined separately, or at least in appendices, with an expectation that the workaround will eventually be obsolete. [Failure here implies that the resource interfaces are object-specific, not generic.]
Me: This potentially implies that "Profile" is one such workaround although I'm not certain of this interpretation.
Roy: A REST API should never have “typed” resources that are significant to the client. Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client. The only types that are significant to a client are the current representation’s media type and standardized relation names.[ditto]
Roy: A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations. The transitions may be determined (or limited by) the client’s knowledge of media types and resource communication mechanisms, both of which may be improved on-the-fly (e.g., code-on-demand). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]Me: This is where the generic media type failed the RESTful test and why specific media types are RESTful. My using a generic media type with data that is not defined in that media type's representation you are "typing" a resource, which is no-no. I'm not sure but I believe the use of a profile and/or JSON schema both attempt to "type" generic media types.
Me: This explicitly discredits the assertion that "Inventing your own media type introduces coupling which is very not-RESTful and something that Roy argues against in that blog post." It is coupling, but according to Roy's it is good coupling. There will be more on this below.
Roy: To some extent, people get REST wrong because I failed to include enough detail on media type design within my dissertation. That’s because I ran out of time, not because I thought it was any less important than the other aspects of REST.
Me: Here Roy is putting an emphasis on media types. This imply Roy's focus on media types, not a belief that media types introduce (bad) coupling. There will be more on this below.Roy: Automated agents are dependent on their understanding of the media types, link types, or microformat extensions provided in representations. It is the same basic issue as with human communication: we will always need a common vocabulary to make sense of it. Exposing that vocabulary in the representations makes it easy to learn and be adopted by others. Some of it will be standardized, some of it will be domain-specific, but ultimately the agents will have to be adaptable to new vocabulary.
Me: We are starting to get to the smoking gun. Here Roy is saying that clients need to have knowledge of the media type and that is what you (I think mistakenly) say is non-RESTful. Instead I believe Roy is saying that it is exactly RESTful.
Roy: Every media type defines a default processing model. For example, HTML defines a rendering process for hypertext and the browser behavior around each element. It has no relation to the resource methods GET/PUT/POST/DELETE/… other than the fact that some media type elements will define a process model that goes like “anchor elements with an href attribute create a hypertext link that, when selected, invokes a retrieval request (GET) on the URI corresponding to the CDATA-encoded href attribute.” Identifiers, methods, and media types are orthogonal concerns — methods are not given meaning by the media type. Instead, the media type tells the client either what method to use (e.g., anchor implies GET) or how to determine the method to use (e.g., form element says to look in method attribute). The client should already know what the methods mean (they are universal) and how to dereference a URI.
Me: Here it gets even more clear that Roy is saying that the client needs to be coupled to an understanding of the media type.Roy: The interface doesn’t need to be discovered. It is defined right there in the hypertext. The representation tells the client how to compose all transitions to the next application state. This could be as simple as an anchor or as complex as a java applet.Me: Here I believe Roy is saying that a client should not (need to) use external schemas (or profiles) to discover how to process a media type but instead that a client should fully understand the media type. Indeed, that's the whole point of a media type; to enable to client that see the media type string in the Content-type header to be able to say "Oh, I know that is and I know exactly what I need to do to process it." Using a generic media type and processing it specifically with or without an externally discoverable interface is thus not RESTful.Roy: HTML doesn’t need type specifications. No RESTful architecture needs type specifications. Don’t expect REST to act like some other architectural style. You don’t get to decide what POST means — that is decided by the resource. Its purpose is supposed to be described in the same context in which you found the URI that you are posting to. Presumably, that context (a hypertext representation in some media type understood by your client) tells you or your agent what to expect from the POST using some combination of standard elements/relations and human-readable text.
Roy: 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.Me: Here it gets even more clear that 1.) using a schema (and maybe even a profile) is not RESTful, and clients should have in-built understanding of the media types they process.
Me: And it gets ever so more clear here. A client must have prior knowledge of a media type for such a system to be consider RESTful. This completely contradicts the assertion (that) "Inventing your own media type introduces coupling (an interface specific to your API) which is very not-RESTful and something that Roy argues against in that blog post."
Roy: In terms of testing a specification, the hardest part is identifying when a RESTful protocol is actually dependent on out-of-band information or if the authors are just overspecifying things for the purpose of documentation. What I look for are requirements on processing behavior that are defined outside of the media type specification. One of the easiest ways to see that is when a protocol calls for the use of a generic media type (like application/xml or application/json) and then requires that it be processed in a way that is special to the protocol/API.
Me: And here I don't think it can get more explicit than this: using a generic media type like application/json is not RESTful.
Roy: The media type identifies a specification that defines how a representation is to be processed. That is out-of-band information (all communication is dependent on some prior knowledge). What you are missing is that each representation contains the specific instructions for interfacing with a given service, provided in-band. The media type is a generic processing model that every agent can learn if there aren’t too many of them (hence the need for standards). The representation is specific to the application being performed by the agent. Each representation therefore provides the transitions that are available at that point in the application.
Me: This is what I was referring to as "Good Coupling" above. He explicitly states that clients are coupled to media types using "out-of-band-information."
Roy: That doesn’t mean that I think everyone should design their own systems according to the REST architectural style. REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them. That’s fine with me as long as you don’t call the result a REST API. I have no problem with systems that are true to their own architectural style.
One final point about media types and that is that too many media types is just as bad as too few:Me: And here's the qualifier; your system doesn't have to be RESTful. But when giving advice on a former where RESTfulness is often assume I think it's implies that advice should come with a disclaimer that the advice deviates from RESTfulness.
Roy: The media type identifies a specification that defines how a representation is to be processed. That is out-of-band information (all communication is dependent on some prior knowledge). What you are missing is that each representation contains the specific instructions for interfacing with a given service, provided in-band. The media type is a generic processing model that every agent can learn if there aren’t too many of them (hence the need for standards). The representation is specific to the application being performed by the agent. Each representation therefore provides the transitions that are available at that point in the application.
Me: What this means to me is that media types that can combine use-cases are better than having lots of media types because it can result in fewer media types. And ideally, there would not be one media type per vendor for a broad problem domain but a collaboration between vendors such that there is only one media type for a given problem domain.
It's a concern for efficiency, and the reason the client-server constraint exists in REST. You should be able to figure out which internal path to route the data stream to by looking at the headers, without needing to buffer an uploaded file in memory, then parsing it, then routing it to the appropriate function. Routing data is metadata, and it doesn't belong in the entity-body (or at least not exclusively).
This issue doesn't come up in HTML because people don't typically use HTML for their APIs. Those who do will find themselves running up against the same problem. My arguments apply equally to all media types.
I believe what you are referring to the need for an intermediary on the network such as a router to not have to look at the body vs. the client having to look or not look into the body. So I don't buy your routing concern as a reason to create many different media types for each use-case, at least not without a good example where you'll need to route something differently.
What's an example of a media type crafting in the form of HTML where there are many optional elements/properties where an intermediary needs to reach in and see data that IMO only a client needs to see. This seems to me to be abstract concern without a use-case, not a real concern.
Of course if you do find a use-case where reaching into the body for routing becomes a serious issue then go ahead and make multiple media types. But don't arguing against a single media type unless you have specific known instances of this specialized need for routing for specific problem domains. I assert that in the vast majority of cases you will not.
Anyway, back to Roy: REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them. That’s fine with me as long as you don’t call the result a REST API. I have no problem with systems that are true to their own architectural style.
Me: I think this is pretty clear that REST is not about efficiency.
None of our solutions were (completely) RESTful to begin with, and this point doesn't uniquely impact my proposal any more than anyone else's.
Which solutions are you reference to, explicitly?
If you want all the benefits you're discussing, you're going to have to use HTML.
Wrong, RSS and ATOM have those same benefits, when used for their originally intended use-cases and those can be used for automated processing in addition to human processing.And there are probably others I don't know of or can't think of right now.
You're not supposed to memorize them, they're there for the benefit of machines.
I've heard that argument so many times and I still can't believe people make it. I remember when people use to say that users didn't need to understand URLs and yet look at how apps like Twitter have leveraged the URL to be something that most users understand and know how to deconstruct and then use the deconstructed components and/or to construct new URLs. I think that recent history has shown that the things that have taken hold have more often than not been easily grokable by humans. It's only when businesses push employees to use complex solutions (like many of those provided by Microsoft, Oracle, SAP, etc.) that complexity is allowed to perpetuate.If you make something that is designed for machines but not humans then fewer humans believe at first glance that they can understand it, so fewer humans ultimately try to understand it. I can't tell you how many people I've trying to teach HTML to that have struggled with those old DOCTYPEs. And I don't know for sure how many web pages exist on the web that don't have DOCTYPEs but I can assure you its not an insignificant percentage and my assertion is that if it were easy it wouldn't be an issue.Why has JSON overtaken XML as the representation of choice for most new web services these days? Because it's so much easier for humans to deal with than XML is. We can read it, there are no namespaces to have to figure out, there is limited complexity in JSON (no attributes, no namespaces, etc.) and JSON is very easy to process is most programming languages; not so with XML, because of its complexity.
Now we have no way of differentiating HTML from other vocabularies, except doing so in a media type. This isn't such a bad thing for user agents speaking HTTP or MIME, but it very much impacts writing files to a filesystem, among other things (not something we're concerned with in this API, or is otherwise easily mitigated). (And unfortunately some of the recent editors seem to think the only kind of user agent that will ever use HTML are Web browsers.)
I don't understand this concern at all. Maybe you can give use-case examples?
But again, a custom media type becomes inaccessible to generic user-agents.
I think my long exegesis of Roy above covers why generic user-agents are not RESTful so I concern for generic user-agents in context of REST is moot.
Try serving a webpage as text/vnd.example+html, see what happens. It loses its status as hypertext. You've now reduced an HTTP API to a mere RPC.
Correct, but you are taking it in the wrong direction. If you really need text/vnd.example+html then build a client that understands it. But that makes little sense if it is something to be consumed by users where billions of text/html user agents have been deployed.Remember, you have been arguing for API usage so an example that modified HTML does not apply to this discussion unless you want to process as an API in which case build a media-type specific client.
I never said any application should require JSON Schema, just that you can serve a JSON Schema at the (otherwise opaque) profile URL, to the benefit of generic user agents: A generic user agent, if aware of a JSON Schema that describes a JSON response, automatically generate an editable form and process and present Link relations. This supports the REST notion that the server and client can independently evolve.
-MikeAgain, not sure based on Roy that doing so is RESTful. But I'm still learning, maybe it is?
Here I believe Roy is saying that a client should not (need to) use external schemas (or profiles) to discover how to process a media type but instead that a client should fully understand the media type. Indeed, that's the whole point of a media type; to enable to client that see the media type string in the Content-type header to be able to say "Oh, I know that is and I know exactly what I need to do to process it." Using a generic media type and processing it specifically with or without an externally discoverable interface is thus not RESTful.
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.
Do you understand what a generic user-agent is? It's something like a web browser, or web spider or robot, that doesn't consume any particular API, and can be used to interface with _any_ supported media type, such as JSON, RSS, or HTML over HTTP.
Is seems to me that "generic user-agent that doesn't consume any particular API" and "supported media" are mutually exclusive concepts.
REST is specifically designed for the benefit of these generic user agents, so that without knowing anything about what the API does, it can see hyperlinks, see declarations on how one resource relates to another, and follow those hyperlinks, as well as perform actions, like constructing a URL or a POST entity-body from a form, as specified by the server (as opposed to the client needing to understand ahead of time how to construct a POST entity-body).
It's seems clear to me that we both have our own respective understandings of what it REST and REST what is not and our understandings are apparently conflicting. Thus one of our understandings by definition must be wrong. Either that or we are not understanding each other.
In Roy's language, adding the "profile" does not create a new media type, it specifies that the enclosed content-type is a subset of that media type. <http://tools.ietf.org/html/rfc2046> provides information on the semantics of media type parameters.
Nowhere in RFC 2046 did I find the word "profile"; instead I found this which is very similar to your quote but discussing something different (emphasis mine):
In general, the top-level media type is used to declare the general type of data, while the subtype specifies a specific format for that type of data. Thus, a media type of "image/xyz" is enough to tell a user agent that the data is an image, even if the user agent has no knowledge of the specific image format "xyz".
So that's referring to "json" in the "application" part not a profile (which is still only a draft[1]), and further RFC 2046 is in context of MIME, not RESTful systems. Yes HTTP uses Content-Types but RFC 2046 was written about email, not about RESTful APIs.Lastly I don't see anywhere where Roy participated in RFC 2046 nor have I seem him advocate profiles for Content Types.BTW, I think James Snell has the right take on Profiles and Media Types:
In quotes, you bold the wrong text. It should read:
I bolded exactly the text I intended to bold. The fact you would bold something else does not make my choice wrong, it's just different from your choice.
"One of the easiest ways to see that is when a protocol calls for the use of a generic media type (like application/xml or application/json) and then requires that it be processed in a way that is special to the protocol/API."
Using what you bolded, that says to me that if you process application/json in a way that recognizes any structure beyond what is defined here: http://www.ietf.org/rfc/rfc4627.txt then you are not processing it in a RESTful manner.
A generic media type is not only RESTful, but required
Please provide references where this is stated because my understanding is that use of generic media types for anything beyond what's define in their spec is not RESTful.
What makes usage of a generic media type in an API not RESTful is when you require that the media type is handled in some way special to the API. This is comparable to visiting a website, and it tells you "Your web browser must treat the <pre youtube-src="..."> tag with our special provided plugin in order to play videos". This is "processed in some way special to the API", and this is not RESTful. A media type must act consistently no matter what API it is being used with.
Reviewing this I agree. But reading (most of) what else you've written I can't help but think that your understanding of "special to the API" is very different from my understanding of that same phrase. To me "special to the API" means the API is using the media type in a manner that is not defined in the media type specification. Period.For example, in HTML there is an <a> tag and am <img> tag; the former has @href and the latter @src but while both accept URL values the browser processes those URLs differently and the browser has in-build knowledge of <a @href> vs. <img @src>.Similar if you received a representation in the generic media type application/json like below and your client was programmed to navigate to the "href" in the "a" link then it would be doing something "special to the API" and would thus be non-restful because the JSON does not define the meaning of "a" nor "href" and especially not what the value of "cart" means for "rel":{"a": {"rel": "cart","href": "http"//api.example.com/cart"}}
The thing he is talking about is requiring specialized knowledge in order to interface with an API. A generic user agent like my web browser should be able to pull up a website and just use it, never having seen it before.
We are talking about media types for use with APIs; why keep bringing up browsers loading websites?
If you want to add special, optional behavior to your API, then fine, but that's RPC behavior on top of the RESTful part of your API.
How do you make the leap from optional behavior to "then it must be RPC?"
A schema is provided as a link, any generic client can follow that link, and any generic client can understand JSON Schema, and imbue the received JSON with meaning. What he is describing here is introducing application-specific behavior, like the "youtube:player" tag that I talked about.
My understanding is that creating discoverable interfaces is not what Roy intended for REST; to whit (emphasis mine):
Roy: The interface doesn’t need to be discovered. It is defined right there in the hypertext. The representation tells the client how to compose all transitions to the next application state. This could be as simple as an anchor or as complex as a java applet.
The REST API I am proposing is not typed, to a REST client, it is application/json (strictly, this still isn't RESTful as JSON lacks hypertext.
Correct, it's not RESTful.
If the client were provided a Link header to the JSON Hyper-schema, it would become more RESTful.).
It's not RESTful according to my interpretation of Roy's statement:
"The interface doesn’t need to be discovered. It is defined right there in the hypertext."
Also note that he says media types and URIs are provided for the benefit of the server; the server is allowed to treat a specific media type as special, or to treat a particular URI format as special. A client is not.
-MikeAgreed, but I don't see the relevance in this discussion.
So... What are the actual, practical differences in evolvability between a versioning technique using profiles than one using custom media type identifiers?
Is seems to me that "generic user-agent that doesn't consume any particular API" and "supported media" are mutually exclusive concepts.
REST is specifically designed for the benefit of these generic user agents, so that without knowing anything about what the API does, it can see hyperlinks, see declarations on how one resource relates to another, and follow those hyperlinks, as well as perform actions, like constructing a URL or a POST entity-body from a form, as specified by the server (as opposed to the client needing to understand ahead of time how to construct a POST entity-body).It's seems clear to me that we both have our own respective understandings of what it REST and REST what is not and our understandings are apparently conflicting. Thus one of our understandings by definition must be wrong. Either that or we are not understanding each other.In Roy's language, adding the "profile" does not create a new media type, it specifies that the enclosed content-type is a subset of that media type. <http://tools.ietf.org/html/rfc2046> provides information on the semantics of media type parameters.Nowhere in RFC 2046 did I find the word "profile"; instead I found this which is very similar to your quote but discussing something different (emphasis mine):In general, the top-level media type is used to declare the general type of data, while the subtype specifies a specific format for that type of data. Thus, a media type of "image/xyz" is enough to tell a user agent that the data is an image, even if the user agent has no knowledge of the specific image format "xyz".So that's referring to "json" in the "application" part not a profile (which is still only a draft[1]), and further RFC 2046 is in context of MIME, not RESTful systems. Yes HTTP uses Content-Types but RFC 2046 was written about email, not about RESTful APIs.Lastly I don't see anywhere where Roy participated in RFC 2046 nor have I seem him advocate profiles for Content Types.
BTW, I think James Snell has the right take on Profiles and Media Types:
In quotes, you bold the wrong text. It should read:I bolded exactly the text I intended to bold. The fact you would bold something else does not make my choice wrong, it's just different from your choice.
"One of the easiest ways to see that is when a protocol calls for the use of a generic media type (like application/xml or application/json) and then requires that it be processed in a way that is special to the protocol/API."Using what you bolded, that says to me that if you process application/json in a way that recognizes any structure beyond what is defined here: http://www.ietf.org/rfc/rfc4627.txt then you are not processing it in a RESTful manner.
A generic media type is not only RESTful, but requiredPlease provide references where this is stated because my understanding is that use of generic media types for anything beyond what's define in their spec is not RESTful.
What makes usage of a generic media type in an API not RESTful is when you require that the media type is handled in some way special to the API. This is comparable to visiting a website, and it tells you "Your web browser must treat the <pre youtube-src="..."> tag with our special provided plugin in order to play videos". This is "processed in some way special to the API", and this is not RESTful. A media type must act consistently no matter what API it is being used with.Reviewing this I agree. But reading (most of) what else you've written I can't help but think that your understanding of "special to the API" is very different from my understanding of that same phrase. To me "special to the API" means the API is using the media type in a manner that is not defined in the media type specification. Period.
For example, in HTML there is an <a> tag and an <img> tag; the former has @href and the latter @src but while both accept URL values the browser processes those URLs differently and the browser has in-build knowledge of <a @href> vs. <img @src>.
Similar if you received a representation in the generic media type application/json like below and your client was programmed to navigate to the "href" in the "a" link then it would be doing something "special to the API" and would thus be non-restful because the JSON does not define the meaning of "a" nor "href" and especially not what the value of "cart" means for "rel":{"a": {"rel": "cart","href": "http"//api.example.com/cart"}}
The thing he is talking about is requiring specialized knowledge in order to interface with an API. A generic user agent like my web browser should be able to pull up a website and just use it, never having seen it before.We are talking about media types for use with APIs; why keep bringing up browsers loading websites?
If you want to add special, optional behavior to your API, then fine, but that's RPC behavior on top of the RESTful part of your API.How do you make the leap from optional behavior to "then it must be RPC?"
A schema is provided as a link, any generic client can follow that link, and any generic client can understand JSON Schema, and imbue the received JSON with meaning. What he is describing here is introducing application-specific behavior, like the "youtube:player" tag that I talked about.My understanding is that creating discoverable interfaces is not what Roy intended for REST; to whit (emphasis mine):Roy: The interface doesn’t need to be discovered. It is defined right there in the hypertext. The representation tells the client how to compose all transitions to the next application state. This could be as simple as an anchor or as complex as a java applet.The REST API I am proposing is not typed, to a REST client, it is application/json (strictly, this still isn't RESTful as JSON lacks hypertext.Correct, it's not RESTful.
If the client were provided a Link header to the JSON Hyper-schema, it would become more RESTful.).It's not RESTful according to my interpretation of Roy's statement:"The interface doesn’t need to be discovered. It is defined right there in the hypertext."
...
This discussion between you and me has become circular. I've already addressed each of your points at least once except for the strawman arguments you attributed to me that I did not make.Since we are the only two debating on this branch of this thread it appears no one else cares to be drawn into a circular argument and thus our debate have little overall value. Rather than waste several more hours continuing this debate I will bow out at this time.
So... What are the actual, practical differences in evolvability between a versioning technique using profiles than one using custom media type identifiers?