I'm developing an API using ruby and Sinatra for an already existing Rails App. I've separated the applications (no mounting logic), and these are therefore being deployed separately. On production I'm using nginx as my proxy server for both applications, which uses domain-matching to dispatch to the right application.
I'm also versioning my API. Currently I'm doing it in the Sinatra application itself, by overwriting the methods which get, post, the filters, etc... call, so, whichever string or regex rules you apply to match the request uri, they'll have the versioning before them added:
# matches /v0.1/resource/:id
get "/resource/:id" ....
this has the disadvantage of always having to match at least the start of the url, first / included, otherwise the version number will not be rightly added. Not only that, that means I also only match one version of the API per application.
I'm still working on the first version, so there's time to figure out the best strategy to move on as version bumping of the API ensues. I see two possible strategies:
Make it all a la Rails (as they recommend on the railscast for rest API versioning) and version the matching all the time in the app:
get "/0.1/resource/:id" do ..... get "/0.2/resource/:id" do .....
this has the disadvantage of always having two (or more) versions of the logic, making the url matching logic more complex (like, if I want to match all with one rule like /\d+/resource/\d+, then I'll have to still see if the version number is acceptable) and increase overall the spaghetti occurrences, in my eyes.
it has the advantage of maintaining the same deploy logic (replace the last version by the current, nginx routes only to one API, etc...).
Let nginx dispatch by version. Using CVS I can version my code. I'd just have to define how many versions of it would I want to support online, deploy them, and then rearrange the nginx routing, which would be now domain+version based.
This has the advantage of cleaning the application logic, since I only match the necessary rules for the logic. using the last example:
get "/resource/:id" do ....
and nginx would take care of routing to the right application.
this has a few technical disadvantages though: for this to work, I'll have to change the deploy strategy, in that I have to choose how many versions of the API I support, fetch them from my CVS, then edit nginx configuration, delete the last API rules, insert the new ones (route to api.myapp.com/v1, api.myapp.com/v2...) and reinitialize nginx. The other disadvantage is that now I have to support more than one API code basis, for instance for bug fixing... which is the same as the above, I'll just have to support the different version-tagged code basis.
I would like to know how others have solved this issue in their cases, and how that influenced the subsequent maintenance.