3 ms·
Neither of the schemes mentioned here are good as they change the URI for a resource, which breaks all sorts of things. Could you imagine if every website want
by JimDabell 10y ago
Neither of the schemes mentioned here are good as they change the URI for a resource, which breaks all sorts of things. Could you imagine if every website wanting to switch from HTML 4 to HTML 5 had to update their URIs from https://www.example.com/HTMLv4/contact.html https://www.example.com/HTMLv4/contact.html to https://www.example.com/HTMLv5/contact.html https://www.example.com/HTMLv5/contact.html? It would be chaos.
For instance, if client application A talks to the service using version 1.0 of the API and client application B talks to the service using version 2.0 of the API, then those client applications can't interoperate because they are seeing two different sets of resources.
Your solution isn't far off the approach recommended by everybody who rejects the different URI approach. You don't need an API version header. When your representation format for a resource changes, provide a `version` parameter for the media type. For example: `Content-Type: application/vnd.example.foo+json;version=2`.
This is exactly how HTTP and the `Content-Type` header are supposed to work – if your representation for a resource changes, you don't change the URI, you change the media type.
- jdmichal 10y agoInterestingly enough, putting it in Content-Type is also invalid unless the mime type allows it. (Which, of course, is trivial if you're defining your own.) Specifically, RFC 2616 specifies that clients SHOULD only specify parameters which are valid for the mime type [0]. This can get more restrictive; for instance, JSON-API (application/vnd.api+json) states that any parameters MUST result in 415 UNSUPPORTED MEDIA TYPE [1]. [0] https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.... [1] http://jsonapi.org/format/ http://jsonapi.org/format/
- ChrisAtWork 10y agoThe "?api-version" approach in the doc is there for exactly the reason you call out. Azure uses this approach. By omitting "/v1.0" from the path it makes the actual URL's far more durable, as they're not version dependent. There are pros and cons to this, as there is with everything. In Azure's case it's great, as you can then use URLs as resource identifiers and put ACL's on them. If they were versioned via the path, this wouldn't work. Other services, such as XBox, and (very old) Azure, put the API version in a custom header (x-ms-version, for example). This proved to be extremely problematic, and every team that does this had stories of all the problems it caused and then spends time removing it. I've never seen a detailed proposal for putting API version in the Content-Type header, and will go look. The content-type header does seem to have many of the same drawbacks as putting the version in a header (any header). For example, people could not make queries from a browser just by entering a URL as there is no way to specify a header. Nor could someone bookmark an API GET request, which is also quite handy. Ease of use is huge, and I am in the camp that a version in the URL (path or parameter) is much easier in every way than a header. Every with curl, it's easier (I can never remember how to specify headers w/o the man page).
- pdrayton 10y agoOne slight downside of a custom header to specify a version is that OPTIONS calls don't include the value of the custom header, so your pre-flight gets to say yes or no without knowing what version is being called. Putting API version in the URL or query string fixes this. As for bookmarking a GET request, this is /almost/ doable even following the MSFT guidelines since it says that service implementors MUST also provide a query-string alternative to required custom headers (section 7.8), and that service implementors MUST support explicit versioning. The only fly in this ointment is that the versioning part of the spec only offers two places of specifying the version - URL and query string, and seems to leaves no room for other options. Personally, I think the Accept header flavor with custom MIME types is the most flexible for minor (backwards compatible) version - see GitHub's API for an example - but it certainly isn't the most simple to work with, neither in client libraries, Curl/WGet command-line use or API consumer tools (almost none let you fiddle with Accept headers). Since API ease of use is such a big factor for adoption, passing versions in the URL or the query string is most likely an OK lowest common denominator for APIs that seek the widest possible reach.