In IRC eaton raised the perfectly valid concern that having an API endpoint different to the drupal root, would help with future API changes. E.g. let's consider Drupal major version upgrades.

It appears that the suggested approaches for that are
a) provide versioned and un-versioned URIs at the same time
b) have stable URIs and do versioning via media types.

Some resources:
http://stackoverflow.com/questions/389169/best-practices-for-api-versioning
http://stackoverflow.com/questions/972226/how-to-version-rest-uris
http://barelyenough.org/blog/2008/05/versioning-rest-web-services/

Comments

fago’s picture

@eaton:

Fago and I had a chat yesterday in IRC about the endpoint URL issue; although I can't speak for him, I think we nailed down a useful idea regarding the URLs. Versioning via different endpoint URLs is pretty much standard at this point, although it's also standard to have /api as the url of the current api version. Using native entity URLs by default makes moving TO a versioned API very very difficult, but it would be possible to supply optional menu callbacks on the entities themselves, aliasing those to the normal API callback URLs.

For example, node/%node/json could simply be an optional pointer to api/node/%node/json.

I'm still unsure about the best way to deal with that.

Having "api/node/%node" would mean we would have to also return URIs in the format of "api/node/%node" for any referenced resource. So any reference that is kept on the client side, would automatically point to a specific API version. Having that, it's hard for the client to migrate to a new API version as all references would have to change.

So what about using *optional* GET parameters for API versions? That way it's easy to keep them out of the URI, so references stay intact across API versions and a client can easily check between API versions just by appending the right GET parameter, ala ?api=1.
Then we nevertheless need a hook that allows modules to alter how specific requests are handled. So modules could use that hook to look at the GET parameter and to pass the request to a different implementation if necessary.

Thoughts?

klausi’s picture

So for an example GET request we would have the following three options:

* GET example.com/node/123?api_version=1.0 (HTTP Accept: application/json)
* GET example.com/node/123 (HTTP Accept: application/vnd.drupal.node-v1.0+json)
* GET example.com/api/1.0/node/123 (HTTP Accept: application/json)

lsmith77’s picture

here is another link that could be interesting for the topic:
http://www.informit.com/articles/article.aspx?p=1566460

I am also working on this topic for Symfony2:
https://github.com/FriendsOfSymfony/FOSRestBundle/pull/136

Which is already being used a library in Silex:
https://github.com/flintstones/Rest

Maybe there is a potential to unbundle some stuff into a proper library that could be reused with Drupal8 now that its adopting the Symfony2 HttpFoundation:
http://drupal.org/node/1178246

Obviously this would help little/less for Drupal7 and earlier

klausi’s picture

So you are following the pattern "GET example.com/node/123 (HTTP Accept: application/vnd.drupal.node-v1.0+json)", right?

I'm still not convinced that this is the best option. What version is returned in the default case "GET example.com/node/123 (HTTP Accept: application/json)"? The most recent one? Or 406 not acceptable is returned?

lsmith77’s picture

@klausi: thats up to you to define. though i am not sure what the best practice is .. will ask David Zülke (http://www.slideshare.net/Wombert/designing-http-interfaces-and-restful-...)

but in general why URL versioning is bad (see above slides) .. my attempt at explaining it here:
the reason why you don't want to version by URL is that this would mean that you would be saying that v1 of the same resources is not the actually the same resource as v2. now imagine you write an application that stores links to tweets for example to handle additional comments (twitter uses URL versioning) and now twitter updates its API and you update your application to also support the new API .. suddenly you will have to do a lot of heavy lifting to prevent the comments to stay together.

furthermore imagine you have an application that works fine with v1 and the provider publishes infos on v2 which provides additional features. with URL versioning you will have to make a manual switch over at some point. with media type based versioning you can simply implement v2 on your end and state that you prefer v2 in your accept header over v1 and as soon as v2 is publicly available your application will use it without you having to do a manual switch over.

Crell’s picture

Priority: Normal » Major
Issue summary: View changes

Bumping this per today's WSCCI meeting. Also setting to Major priority: We don't need to have versioning completely in place for D8, but we need to know what we're doing for it by D8 even if the work gets done later.

timwood’s picture

Just wondering any plans to work on this for D7?