API Endpoint Sub-domain and Versioning
Utilizing a sub-domain for your API is incredibly useful, it allows for utilization of the same domain for a landing page or other web features. For commercial websites you could also use this feature to create a demo page (i.e. www.myproduct.com, demo.myproduct.com).
Luckily Rails makes creating a sub-domain for your API incredibly simple. Along with easily creating a sub-domain, Rails makes it a snap to add versioning. Versioning allows for easy creation of different versions of the API while still including support for the previous version.
In order to achieve a sub-domain versioned API first, in the routes.rb file, create a namespace and scope:
namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :products
end
end
By defining a namespace under the routes.rb file. Rails will automatically map that namespace to a directory matching the name under the controllers folder. In this example it is the api/ directory.
In this example the default API version is set to 1 and the version specific API controllers can be created in controllers/api/v1 of your rails project.
Lastly, the scope module allows for setting the current version of the API in the accept header which removes the version from the URL and allows the description to be handled by the header. In order to correctly select a version the api_constraints.rb class is created and contains a matches? method to see if the default version is required or the Accept header matches the given string.
class ApiConstraints
def initialize(options)
@version = options[:version]
@default = options[:default]
end
def matches?(req)
@default || req.headers['Accept'].include?("application/vnd.myapp.v#{@version}")
end
end
In order to run the sub-domain locally I use pow and powder.
It is worth noting that Heroku does not support subdomains on their Heroku URLs making it necessary to purchase your own domain name and utilize that to test your new API.