Rails Web API Versioning

1 minute read

[2013-12-18 Why was so I attracted to the idea of versioning web APIs? I’ve never needed this.]

One way to make different versions of a web service available from the same webserver is to allow clients to prepend a version identifier to the URI path. There’s some discussion about the best way to use this but I like to default to no version identifier in URIs.

Passenger makes it easy to run different versions of your Rails web api alongside each other.

  • http://brandish.local/customers.json
  • http://brandish.local/v1/customers.json
  • http://brandish.local/v2/customers.json

Update Your Webserver Config

Passenger allows you to direct traffic to different instances of your app. Here I’m serving brandish_v2 if no version identified is included in the URI.

<code># /etc/apache2/sites-available/brandish
<VirtualHost *:80>
  ServerName brandish.local
  CustomLog /var/log/apache2/brandish_access_log combined
  RackEnv development

  DocumentRoot /srv/brandish_v2/public
  RackBaseURI /v1
  RackBaseURI /v2
  <Directory /srv/brandish_v2/public/v1>   
    Options -MultiViews  
  </Directory>
  <Directory /srv/brandish_v2/public/v2>   
    Options -MultiViews  
  </Directory>
</VirtualHost>
</code>

This is the only tricky bit. Passenger expects the RackBaseURI’s you used in the web config to point at symlinks to the public/ directories of the different versions of your apps.

<code>ln -s /srv/brandish_v1/public -> /srv/brandish_v2/public/v1
ln -s /srv/brandish_v2/public -> /srv/brandish_v2/public/v2
</code>

Note Passenger was failing for me because it expected application.rb to be in controllers directory. I fixed it by creating a symlink from application_controller.rb to application.rb. I’m a bit confused as I thought that had been fixed in recent versions of Passenger. Maybe the RailsBaseURI code is not up to date.