Versions

Introduction

Often an API will need to have multiple versions available. This can allow new functionality to be restricted for e.g. internal use or to ensure backwards compatibility with an older vesion.

Flappi supports a system of semantic versioning and flavouring.

Semantic versioning is a standardised way of labelling ordered releases. An example would be to have versions: V1.0, V2.0, V2.1, V2.1.1, V3, V3.0.1

Flavouring allows one release to have multiple flavours, e.g: V3.0, V3.0-internal, V3.0-mobile.

Providing the version

The version will generally be provided in the request, e.g: https://api.example.com/v2.1/cheeses.json (You could also use a header, or imply it).

Flappi expects that the version text is passed in a version parameter. In Rails, this can be done through a namespace in the Rails routes, such asL

namespace :v2, path: 'V2(.:version)' do
 resources :cheeses
 resources :chocolates
end

The configuration (in e.g. 'initializers/flappi.rb') will also need to change to match the version:

conf.definition_paths = { 
  'default' => 'api_definitions', 
  'v2' => 'api_definitions' 
} 

You can use this to direct top level versions to different definition folders.

You now use the URL http://localhost:3000/v2/cheeses.json to do a GET on the cheeses endpoint.

If you have an existing versioning system to fit into, you may want to alter this scheme and maybe change the params[:version] in a base controller.

Version dependent APIs

You may want to provide a different result dependent on the version.

For instance, we can change the name to product_name in V3 (this is a breaking change for an API consumer).

To serve name in V2 and product_name in V3, we can do:

  field :name, version: { equals: 'V2.0' } 
  field :product_name, source: :name, version: { matches: 'V3.*' }

Notice that we use source to map a common source in the backend, and we allow various point versions at V3.

You can specify a version on the object, objects and field methods.

Version plan

It is possible to optionally define a version plan setting out allowable versions and flavours.

module Api
  class FlappiVersionPlan
    extend Flappi::VersionPlan

    # Version numbers are of the form [text][N][,]+[-flavour]

    version 'V2.0.0' do
      flavour :mobile
    end

    version 'v3.0.0' do
      flavour :internal
    end

    flavour ''
  end
end

We now allow: V2.0.0, V2.0.0-mobile, V3.0.0, V3.0.0-internal. These can be abbreviated by dropping the trailing zero points, so: V2, V2.0-mobile etc. are legal versions.

This is then configured into flappi:

  Flappi.configure do |conf|
    conf.version_plan = Api::FlappiVersionPlan
    ...
  end  

Version restricted endpoints

Having created a version plan (and routed calls to the same major release to a common definition) it is possible to configure an endpoint to be only available (and documented) for a particular version.

For instance, to limit an endpoint to internal use, we can do:

  def endpoint
    version equals: 'V3.0-internal'
    ...
  end

This makes the endpoint only available with a version of V3.0-internal.

NOTE: limiting access to versions, e.g. by user or OAuth application is not a Flappi concern. You would normally do this in a base controller.