好的,这会有点长:
如果您已经熟悉 Rails,可以查看Rails API gem。该项目致力于从 Rails 中删除基于 JSON 的 RESTful API 不需要的额外内容。
这听起来可能很顺利,但它也有它的缺点。首先,您已经阅读了基本 Rails 功能所需的所有内容,您可能已经习惯了,例如respond_to
. 这可能有点棘手,但是当您发现哪个 rails 模块最初提供了通常捆绑在 Rails 中的ActionController::Base
.
话虽如此,让我举一个例子,说明我上周出于好奇为一个小型 API 项目做了什么:
初始情况
我们有一个主要完成的 Rails 应用程序。一切正常,但它基本上是单片的。一切都由 Rails 框架提供服务。对我们来说幸运的是,所有模型逻辑都捆绑在一个名为core
. 该应用程序本质上允许登录的客户创建可通过最终用户视图搜索的产品。
目标是为此提供一个 RESTful API,它可以更有效地处理并发和更大的数据文件(即 CSV、XLS)。
介绍 Rails API
设计目标让我想到了 Rails API gem。基本安装的工作方式与 Rails 类似,只是调用了脚本rails-api
,即:
rails-api new jsonapi
对我来说,这里的优势是我可以使用core
来自其他应用程序的模型,但没有什么能阻止我将自己的模型引入jsonapi
应用程序。
话虽如此,你可以做所有标准的 Rails 好东西,比如路由等。它遵循相同的约定。话又说回来,标准路由最初只对 JSON 做出反应,这有时会有点令人困惑。
让我举一个处理产品的 API Controller 的例子:
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
明确包含的第二行。这是为了让您的 API 可以通过 HTTP 令牌得到保护。如果您想了解有关保护 API 的更多信息,我建议您阅读 Ryan Bates 的Railscasts 指南。
本质上,您可以ApplicationController
像这样提供一个前置过滤器:
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|
# see if key is valid.
end
end
end
同样,请注意第二行,您必须ControllerMethods
手动包含,否则没有控制器会知道authenticate_or_request_with_http_token
.
延期
您可能知道基于 Rails 约定扩展 API。它的工作方式完全相同,只是默认情况下故意丢失了一些东西。如果您需要更多的 JSON 模板灵活性,我建议添加JBuilder ( Railscast )。
很好,但是客户呢?
就个人而言,当涉及到客户时,有很多选择。最终我发现它归结为你最喜欢什么。我个人可以在 Rails API 之上推荐一个小的node.js层,然后在它前面获得一个基于主干.js 的单页应用程序。如果你愿意,你也可以试试AngularJS 。您还可以围绕它构建另一个 Rails 应用程序,并从控制器操作中调用 API。
它还取决于您想要定位的平台 - 想到 iOS/Android 的本机应用程序。
我做出的选择是 node.js + 主干。它目前对我当时和该项目最有意义。节点层本质上持有与 API 通信所需的 Token,主干应用程序有一个小库来与节点层通信。然而,它可能是一把双刃剑,这取决于你的 API 有多复杂。对于一个小例子,这似乎很好,但是为了将主干应用程序的调用传递给 Rails API,可能会有很多代码重复。
验证
对于身份验证,您可以制作基于客户的 API 密钥(令牌),然后将控制器逻辑限制为仅接受该密钥允许的数据操作。您可以通过节点层管理会话。编辑:这是授权,而不是身份验证。没有什么能真正阻止您将 Authlogic 与 Rails API 一起使用——我还没有测试过它,但它应该可以工作。
我承认我还没有完成这部分 - 我希望其他人可以回答这个架构问题:-)
我希望我能提供一些见解。
PS:如果你想测试你的 API,我强烈推荐httpie(太棒了!)