Comments (13)
A fair point. Has anyone tried a hybrid approach where a version in the URL forces all responses to that version, but if you leave the version out of the URL you can control it via media types?
Versions in the URL is a lot easier for devs newer to HTTP APIs, but versioned media types is way more flexible.
from api-spec.
It looks like the most prominent example of this that I've seen is GitHub's newest API revision. Ultimately, it does seem like a good idea, though in general I favor pragmatic solutions; it seems like the most popular and well-understood way to handle this is to include versions in resource URLs.
I do have some concerns about this; I'd appreciate any feedback you or the community might have, but as @johnsheehan rightly points out in #7, it's easy to see how discussing just how RESTful the API is can be counterproductive.
- Is there a way to make this play nicely with JSONP? (Aside of sidestepping the use of JSONP altogether through use of CORS.)
- If you default to the newest version of the API when sent a generic Accept header (or it's omitted), how badly will that break existing client implementations?
- Is there any precedent for API providers gracefully supporting multiple major versions of their API with this mechanism? I see that GitHub and several others have adopted this, but I don't see anyone who is simultaneously supporting two major revisions of the same API with major changes. GitHub's beta-vs.-v3 change isn't significant enough for the sake of my question, IMHO.
Are there any other examples I should be looking at?
from api-spec.
This is a popular video for demonstrating the benefits of versioned media types: http://oredev.org/2010/sessions/hypermedia-apis
from api-spec.
I do like @johnsheehan's approach.
Is there any precedent for API providers gracefully supporting multiple major versions of their API with this mechanism?
API providers generally deprecate older versions. Is this dependent on whether you provide versioned URLs or versioned media types? I guess it depends on developers of the API to decide how many versions to keep? Maybe there can be some voting mechanism perhaps?
If you default to the newest version of the API when sent a generic Accept header (or it's omitted), how badly will that break existing client implementations?
If the developer so chooses to use versioned media types approach instead, they'll have to know that it comes with the territory: if you don't explicitly state the version, your app will be at mercy when the default resource changes.
from api-spec.
Setting up a media types seems like overkill. Why not a simple http header?
from api-spec.
/sub
from api-spec.
@matthewp the mime type is declared in a simple http header, Content-Type
. Also, native HTTP content negotiation is available for it, so it's possibly the single unique versioning mechanism that is uniform in its interface.
Mark Nottingham (author of several specs around HTTP and hypermedia) wrote a nice intro about API versioning.
To avoid orphaning users, the documentation should make clear that an Accept
header should be sent to indicate the preferred version. Any curl
can do that, much simpler than OAuth for instance. The server can return 406 Not Acceptable when needed, with proper instructions on how to upgrade clients.
from api-spec.
versioning with a media type is probably not a good idea as it results in one of two outcomes, neither of which are very desirable:
- Granularity issues: each granular change to some part of your API requires a bump to the application-wide media type
- Media type explosion: in order to combat the above issue, you end up having to create a media type for every type of resource in your system.
Added to which, if you version via the media type identifier, you are requiring content negotiation (via Accept request header) in order to address a specific version of the resource and that means you can no longer point to it with a URI alone. This makes it more difficult to debug, it also requires you to maintain a central registry where the documentation for your media types can be found.
Alternatively, you can use links to do this. And apply versioning by introducing new link relations pointing to resources with new behaviour. Not only is this granular, since you can isolate a change to the individual links that are effected, but it's also more discoverable if you are using URIs for your link relations, since those link relation URIs can be used to expose the associated documentation - i.e. you end up with an API that is fully discoverable without having to go 'out of band' and search for disconnected documentation somewhere. So a breaking change to a user resource could be introduced like so:
{
"links": {
"http://example.com/rels/v1/user": { "href": "..." },
"http://example.com/rels/v2/user": { "href": "..." }
}
}
I'm aware that links are not currently part of the API design, if you are interested in discussing whether or not that'sa good idea I'd be interested in being involved in that :)
from api-spec.
Hi @mikekelly, nice to see somebody bringing up discussion about links =) I believe any RESTful API should have them, should be hypermedia driven. I have a couple of comments about your approach though.
Granularity issues doesn't depend on the versioning format, depends on how many versions the implementor wants. Doesn't matter if the verions are in URIs or HTTP headers, if there are many versions, there will be granularity (with different grains, though). You don't need to version each resource separately, they can all share the same version number if one of them changes.
REST is mostly about typing link relations, not resources. The resources have a format, and that format can be typed as well (it's the media type), but that's not the type of the resource, just the type of the format. By using something like HAL as the base for the new media type, all resources from the same API can share the same media type (like many different HTML documents can use the same format).
Roy Fielding himself wrote a little about this on his popular "REST APIs must be hypertext-driven" blog post. Quoting him:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]
I'm also not sure what you mean about "more difficult to debug". It's an already sent HTTP header (all HTTP responses should have a content type), and for anyone consuming an HTTP API, dealing with headers should be trivial.
from api-spec.
(Also, there is already a media type for content streams, reusing it doesn't seem so hard).
from api-spec.
@alganet my point about granularity was that bumping all resources to a new version just because of one granular change is a bad thing and something to avoid.
the point about debugging was that when using media types for versioning, if someone has an issue relating to a particular version of a resource - they can't send you a link to that specific version just by pasting a URI into an email/github comment/etc. - they need to give you the URI and the Content-Type to include in your Accept header.
btw, I'm the author of HAL so thanks for bringing it up!! :)
from api-spec.
@mikekelly =D awesome work there! Congratulations.
Increasing a number in the media type version bumps all representations versions, not resources. Resources are the same, have the same URI as before. Changing something in the URI indeed "bumps" all resources to a different thing, which would be the case for /v1/
.
You can have a single URI to point to a single version. Something like http://example.com/foo/bar.json.en-US.v0. URI uniformity can be guaranteed by a (rel=canonical href=/foo/bar
link)[http://tools.ietf.org/html/rfc6596]. When retrieving http://example.com/foo/bar with full content negotiation, a Content-Location: http://example.com/foo/bar.xml.pt-BR.v2
header can be returned to instruct clients about this particular variant location.
This is also a highly cache-compliant solution. With a couple of Vary
tweaks both client and server could benefit a lot from cached negotiated responses.
from api-spec.
Adding an additional media type across the application is bumping the resources (to expose an additional representation), existing representations stay as they are or get removed they don't get 'bumped'.
Obviously you can use a combo of Con-neg, Content-Location and a canonical relation, but this convolution is exactly what I mean by it being 'more difficult to debug'..!
Vary is not a silver-bullet either, see http://www.w3.org/Protocols/HTTP/Issues/vary-header.html
Using separate links for controlling versions is a lot simpler because it avoids all of the issues around Conneg (Content-Location vs 301, Vary etc.) by leveraging what is effectively agent-driven-negotiation of versions:
http://tools.ietf.org/html/draft-ietf-httpbis-p3-payload-16#section-5.2
With agent-driven negotiation, selection of the best representation
for a response is performed by the user agent after receiving an
initial response from the origin server. Selection is based on a
list of the available representations of the response included within
the header fields or body of the initial response, with each
representation identified by its own URI. Selection from among the
representations can be performed automatically (if the user agent is
capable of doing so) or manually by the user selecting from a
generated (possibly hypertext) menu.
Agent-driven negotiation is advantageous when the response would vary
over commonly-used dimensions (such as type, language, or encoding),
when the origin server is unable to determine a user agent's
capabilities from examining the request, and generally when public
caches are used to distribute server load and reduce network usage.
from api-spec.
Related Issues (20)
- Modifying annotations on an existing file doesn't seem to trigger a user stream event HOT 1
- Add "Mentions" to a User's Counts object
- Feature Request: Report Wrong Account Type Endpoint HOT 6
- The documentation for creating a file is incomplete
- Add a way to get messages in a channel containing a hashtag
- Add starring functionality to Messages HOT 1
- Abstract away stars – support generic "actions" with associated counters
- Post Search docs mentions seemingly non-functional has_location parameter HOT 6
- More Stream Faceting parameters HOT 1
- Dead link on the Messaging Basics page HOT 1
- Posts API : Reposts? HOT 3
- Expose which posts/messages a file has been attached to/embedded in HOT 1
- Feature request: Reply to multiple posts HOT 1
- Bug in Interactions endpoint pagination when using interaction_actions without "reply" HOT 5
- Allow searching for posts in the users stream.
- Annotations are not returned when creating a channel HOT 3
- include_inactive ignored by https://api.app.net/channels?ids=… HOT 2
- Wikipedia Markdown link throws a 'Bad request' error HOT 1
- User streaming - Add post hashtag search HOT 1
- Streaming fails to recognise "Upgrade: WebSocket" case insensitive
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from api-spec.