If you change the way a "customerId" is formatted in V2, the idea of providing a "customer" resource hasn't changed, and as a matter of style I think it's cleaner that the URL for the customer record representing a single person doesn't change or suddenly split into multiple resources which really represent one entity. IMO the header-versioned approach expresses the semantic difference you point out cleanly, and in addition does not come with undesirable side-effect of diluting the URI concept.
And even if it were, do you guys propose that if I were to request the same data represented in slightly different ways (say order data grouped by customers or grouped by date) within the same version, I should use headers to distinguish between the two, instead of a query string?
I don't have a strong opinion on query strings but I would suspect performing various actions on a given resource or collections of resources could be handled just as well with plain URLs: /customers/byDate /customers/byName. To me those represent resources comprised of differing collections of customer resources. I'm not sure there's a substantial difference there.
I would consider /customers/byDate to be a resource. It happens to be a collection containing references to other resources (customers) which you can then navigate to directly if you want. You can get the byDate collection/resource in varying represenations; JSON, XML, etc. Same with the individual customer resources contained within the collection.
Here's a thought experiment. Say you write a client for version 1 of a URL-versioned API. While we're at it, let's encode representation in the URL as well (/api/v1/customers/1.xml, /api/v1/customers/2.json). Say your client stores references to these resources, maybe the user can add them to a list of favorites. Now there's an API upgrade and you point your client to /api/v2/*. Do you just go in with a regex and munge the stored URLs? If you call what you're doing REST, now you're breaking HATEOS. What if the URL scheme changes with the new version? Seems quite likely when the developer already doesn't subscribe to the notion of having a single URL for a resource. What if you want to store a representation-neutral link to a resource and the user can toggle their view between them? Do you make the assumption that you can munge the "extension"? That's a lot of brittle, in-band assumptions to make with URLs which are supposed to be opaque identifiers. Seems more flexible to have separate, well-defined mechanisms for handling this stuff.
Disclaimer: I don't have a lot of experience in this area, I'm just arguing for what makes sense to me to explore the ideas. I also acknowledge that plenty of sites use URL-versioned and content-negotiated schemes and have little interest in arguing what's "true REST" but it seems to me that following a stricter interpretation of these concepts does come with some nice benefits.
I would expect that API changes from version 1 to version 2 to often have even more differences than above. They may support different methods, may expose different sets of data, etc. There's no reason why they have to be thought of the same resource.
As for your thought experiment, why not have a version-independent URI that points to the latest version? I don't even understand this whole representation-neutral link - you're going to pick one representation or another. Either the client has to give the version information in a header or an URI. Header manipulation is much harder to deal with in practice and isn't easily supported by every client.
>/orders/groupByCustomer and /orders/groupByDate have the exact same data. The only difference here is representation.
Those are two different resources (made plain within the context of my approach by the fact that they have two different URLs). Those resources are ordered collections. They contain the same totality of resources within them, but ordered collections are not semantically equal if the order is different. Therefore I argue those are two distinct collection resources. The fact that they both contain the same resources is irrelevant because the ordering is central to the identity of the resource here.
The URL is not the representation no matter how you look at it [1]. `/orders/groupByCustomer` identifies a resource which could, for example, give you an XML representation, a JSON representation, a PDF representation, etc., depending on content negotiation.
An API change which introduces different methods and data is fine. A resource returned under the new version will expose that, old versions won't see it. There's no reason why the resources can't be the same across versions, but maybe a request for v2 of Customer returns a zip code now and v1 doesn't. Still the same Customer and you have one URL for it.
As for a version-independent URI that points to the latest version (assuming no version in the header), the argument made elsewhere here is that it can break clients that use it when the API is changed.
> Header manipulation is much harder to deal with in practice and isn't easily supported by every client.
I don't think it's that much harder. Granted, if you're dealing with existing clients that only support a small subset of HTTP your choice of style might be made for you. If I'm designing a brand-new API I think I'd be inclined to say "it's 2012 and this is an HTTP service, deal with it".
PS, Thanks for the interesting discussion. It's definitely making me think this through more deeply than I have in the past.
[1] http://en.wikipedia.org/wiki/Representational_state_transfer...
The concrete behind the abstraction may not change, but URLs don't point to concretes, they point to representations of concretes. If "customer" in v1 returned billing information and names while in v2 just returns GPG public keys and a JPEG of their face, they're not really the same resource even if they're representations of the same customer.
If you've got two different resources representing different aspects of customer data, those don't need to be a separate version because they're distinct resources.
GET / HTTP/1.0
GET / HTTP/1.1
should be GET /v1
GET /v2
and YOU'd have to tell the browser which site uses which version.Wouldn't it be nicer if the browser could tell the server which version of the interface it understands?
It happens that the metadatum follows the URI in HTTP requests. The author can't do that, but he can use a header field to achieve the same.
Hence the idea to use "Accept:" for versioning.
All that the author is going to achieve is to have broken client codes every time he's going to bump his API version because most developers won't bother to check the content-type. Or he has control of both the client and server code and then in that case it doesn't matter.
It's irrelevant which layer this is happening at. The point is that there is a resource address and a resource version. Decoupling those allows you to retain the same resource address for different resource versions - whether this is done for backwards compatibility, multi-language support or other reasons.
"All that the author is going to achieve is to have broken client codes every time he's going to bump his API version because most developers won't bother to check the content-type."
The point of the article was in fact to teach those mediocre developers who "won't bother", to actually bother to understand these concepts.
Educate yourself: http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
It would be nice! However, many packages people want to develop clients for REST APIs with have terrible HTTP support, such as Flash. If you ever see an API that supports a "method" parameter in the URL or POST body, it's because Flash is terrible.