Giter Site home page Giter Site logo

Comments (13)

johnsheehan avatar johnsheehan commented on June 18, 2024

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.

berg avatar berg commented on June 18, 2024

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.

johnsheehan avatar johnsheehan commented on June 18, 2024

This is a popular video for demonstrating the benefits of versioned media types: http://oredev.org/2010/sessions/hypermedia-apis

from api-spec.

simondlr avatar simondlr commented on June 18, 2024

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.

matthewp avatar matthewp commented on June 18, 2024

Setting up a media types seems like overkill. Why not a simple http header?

from api-spec.

abraham avatar abraham commented on June 18, 2024

/sub

from api-spec.

alganet avatar alganet commented on June 18, 2024

@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.

mikekelly avatar mikekelly commented on June 18, 2024

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.

alganet avatar alganet commented on June 18, 2024

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.

alganet avatar alganet commented on June 18, 2024

(Also, there is already a media type for content streams, reusing it doesn't seem so hard).

from api-spec.

mikekelly avatar mikekelly commented on June 18, 2024

@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.

alganet avatar alganet commented on June 18, 2024

@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.

mikekelly avatar mikekelly commented on June 18, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.