Web应用程序中的API版本控制

Coo*_*oop 6 ruby architecture api ruby-on-rails application-design

我目前正在为新网站设计版本化API.我理解如何命名路由,但我坚持在模型中实现版本化方法的最佳方法.

下面的代码示例使用rails框架,但问题的原则应该在大多数Web框架之间保持一致.

路线目前看起来像:

MyApp::Application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :products, :only => [:index, :show]
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

和控制器:

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
Run Code Online (Sandbox Code Playgroud)

显然,我们只是在这里公开了Product上可用的属性,如果你只有一个版本的API,这个解决方案很有用.当您想要发布V2和V2时,需要重新实现产品名称的显示方式(同时保持与V1的向后兼容性 - 至少在短期内)会发生什么?

据我所知,你有几个选择......

  1. 立即放弃对V1的支持并处理后果(最糟糕的解决方案)
  2. 你开始重写to_ [format]方法(我很确定你用as_ [格式]做这个,但这不是重点)包含一个新的属性... name_2- 这似乎同样愚蠢
  3. 实现某种代理类,它只负责暴露我们所追求的方法
  4. 让视图处理创建某种类型的哈希,版本控制器和调用to[format]...

三个和四个是我能想到的唯一有意义的......三个看起来像:

# 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
Run Code Online (Sandbox Code Playgroud)

过去其他人做了什么?

Ner*_*ian 6

而不是一个服务V1和V2和V的应用程序...您为每个版本部署一个应用程序.一个应用程序将回答api.domain.com/v1,然后另一个应用程序将回答api.domain.com/v2等等.

这就是面向服务的应用程序如何最好地组织,每个服务应该是隔离的,一个独立的部署.

从单个应用程序提供所有版本会破坏面向服务设计的目的,因为每次在一项服务中进行更改时,您都需要为所有服务进行测试和部署.