好的,这可能会有点长:
如果您已经熟悉Rails,可以看看Rails API gem。该项目致力于从Rails中删除不需要为基于JSON的RESTful API所需的额外冗余。
这听起来很顺畅,但它也有缺点。首先,您必须阅读所有基本的rails功能,您可能已经习惯了,例如respond_to
。这可能有点棘手,但当您找到最初提供通常捆绑在ActionController :: Base
中的Rails功能的Rails模块时,这是相当直接的。
话虽如此,让我举个例子,说明我上周出于好奇心做的小型API项目:
初始情况
我们有一个基本完成的Rails应用程序。一切都很好,但基本上是单片式的。所有内容都由Rails框架提供。幸运的是,所有模型逻辑都捆绑在名为core
的gem中。该应用程序基本上允许已登录的客户创建产品,然后通过最终用户视图进行搜索。
目标是为此提供一个RESTful API,该API可以更有效地处理并发和较大的数据文件(即CSV,XLS)。
引入Rails API
设计目标让我使用了Rails API gem。基本安装方式与Rails相同,只是脚本名为rails-api
,例如:
rails-api new jsonapi
我在这里的优势是可以使用其他应用程序中的
core
,但我也可以将自己的模型引入到
jsonapi
应用程序中。
话虽如此,你仍然可以做所有标准的Rails操作,如路由等。它遵循相同的约定。不过,标准路由最初只对JSON做出反应,有时可能会有些困惑。
让我给你举个处理产品的API控制器的例子:
class ProductsController < ApplicationController
include ActionController::HttpAuthentication::Token
before_filter :find_product, :except => [:create, :index]
def index
render :json => @products
end
def create
@product = product.new params[:product]
if @product.save
render :json => @product, :status => :created
else
render :json => @product.errors, :status => :unprocessable_entity
end
end
def show
render :json => @product
end
def update
if @product.update_attributes params[:product]
render :json => @product, :status => :ok
else
render :json => @product.errors
end
end
def destroy
if @product.destroy
render :json => @product, :status => :ok
else
render :json => {:note => I18n.t("messages.deletion_impossible")}, :status => :unprocessable_entity
end
end
protected
def find_product
@product = Product.find params[:id]
end
end
这并没有什么特别的。唯一需要注意的是第二行,其中显式包含了
ActionController::HttpAuthentication::Token
。这样做是为了通过HTTP Token来保护您的API。如果您想了解更多关于API安全方面的知识,我建议您查看Ryan Bates在
Railscasts中的指南。
实质上,在
ApplicationController
中提供一个before过滤器,就像这样:
class ApplicationController < ActionController::API
include ActionController::HttpAuthentication::Token::ControllerMethods
[...]
before_filter :restrict_access
[...]
def restrict_access
authenticate_or_request_with_http_token do |token, options|
end
end
end
注意第二行,你必须手动包含ControllerMethods
,否则没有控制器会知道authenticate_or_request_with_http_token
。
扩展
你可以按照Rails约定来扩展API。它的工作方式完全相同,唯一的区别是默认情况下某些内容故意省略。如果需要更灵活的JSON模板,建议添加JBuilder (Railscast)。
很好,但客户端怎么办?
个人而言,在选择客户端方面有很多选择。最终我发现选择取决于你最喜欢什么。我个人推荐在Rails API之上添加一个小型的node.js层,然后在其前面使用基于backbone.js的单页应用程序。如果你想的话,你也可以尝试AngularJS。您还可以构建另一个Rails应用程序并从控制器操作中调用API。
这也取决于您要针对哪个平台-可以考虑iOS / Android的原生应用程序。
我做出的选择是node.js + backbone。目前对我和项目来说最有意义。该node层本质上持有与API通信所需的令牌,而backbone应用程序则具有一个小型库以与节点层通信。但它可能是一个双刃剑,取决于您的API有多么复杂。对于一个小例子,这似乎很好,但是如果只是把backbone应用程序的调用放到Rails API中,那么就会有很多代码重复。
认证
对于认证,您可以创建基于客户的API密钥(令牌),然后限制控制器逻辑仅接受使用该密钥允许的数据操作。您可以通过节点层管理会话。编辑:这是授权而不是认证。实际上,您可以在Rails API中使用Authlogic - 我没有测试过,但应该可以工作。
我承认我还没有完成这一部分-希望其他人能回答这个架构问题:-)
希望我提供了一些见解。
P.S.:如果您想测试API,我强烈推荐httpie (它超棒!)