API versions in web applications

I am currently developing versions APIs for a new website. I understand how to use spaces in routes, but I stick to the best way to implement versions in a model.

The following are code examples that use a rail structure, but the principle of this issue should be consistent across most web frameworks.

Currently, routes look something like this:

MyApp::Application.routes.draw do namespace :api do namespace :v1 do resources :products, :only => [:index, :show] end end end 

And the controller:

 class Api::V1::ProductsController < V1Controller respond_to :json, :xml def index respond_with @products = Product.scoped end def show respond_with @product = Product.find(params[:id]) end end 

So it’s obvious that we’re just exposing the attributes available here, this solution works fine if you only have one version of the API. What happens when you want to release V2 and V2, you need to redefine the way the product name is displayed (while maintaining backward compatibility with V1 - at least in the short term)?

As far as I can see, you have several options ...

  • Remove V1 support immediately and handle the fallout (worst possible solution)
  • You start overriding the to_ [format] methods (I'm sure you do this with as_ [format], but this is next to the dot) to include a new attribute ... name_2 - it seems just as dumb
  • Implement some kind of proxy class that is responsible for exposing only those methods that we after
  • Let the views handle the creation of some hash that is controlled by the controller versions and calls to[format] on ...

Three and four are the only things that I really can think of, it makes some sense ... Three will look something like this:

 # model class Api::V1::Product < Struct.new(:product) def to_json attributes.to_json end def to_xml attributes.to_xml end private def attributes {:name => product.name} # add all the attributes you want to expose end end # Controller class Api::V1::ProductsController < V1Controller respond_to :json, :xml def show respond_with @product = Api::V1::Product.new(Product.find(params[:id])) end end 

What have other people done in the past?

+6
source share
2 answers

Instead of a single application serving V1 and V2 and V ... you are deploying one application for each version. One application will respond api.domain.com/v1, then another application will respond api.domain.com/v2, etc.

Thus, service-oriented applications are best organized, each service must be isolated, independent deployment.

Serving all versions from a single application defeats the goal of a service-oriented design, because every time you make a change in one service, you need to test and deploy for everyone.

+6
source

I think you can override your API if you plan to create different versions. Until you remove URLs and properties in the future, older clients may continue to use your API. Just use v1, v2 etc. As a way to split clients when the APIs are working with a bug or a quirk.

If you are changing the basic architecture, in addition to being able to support the original API, I agree that you need to create proxies for the old platform if you plan to support old clients. For the new system, I would create a whole new endpoint server, as @Nerian suggests.

-1
source

Source: https://habr.com/ru/post/893384/


All Articles