Grape是Ruby中的一個類REST API框架,被設計用於運行在Rack上或彌補已有的web應用框架(好比Rails或者Sinatra),Grape提供了一個簡單的DSL用於方便的開發RESTful APIs。Grape支持common conventions,包括多種格式,子域/前綴限制,內容協商,版本控制等。web
經過gem安裝:json
gem install grape
你的應用通常要繼承自Grape::API,下面的例子暫時了Grape中經常使用的一些特性:api
#config.ru 內容 require "grape" module Twitter class API < Grape::API version 'v1', using: :header, vendor: 'twitter' format :json prefix :api helpers do def current_user @current_user ||= User.authorize!(env) end def authenticate! error!('401 Unauthorized', 401) unless current_user end end resource :statuses do desc 'Return a public timeline.' get :public_timeline do Status.limit(20) end desc 'Return a personal timeline.' get :home_timeline do authenticate! current_user.statuses.limit(20) end desc 'Return a status.' params do requires :id, type: Integer, desc: 'Status id.' end route_param :id do get do Status.find(params[:id]) end end desc 'Create a status.' params do requires :status, type: String, desc: 'Your status.' end post do authenticate! Status.create!({ user: current_user, text: params[:status] }) end desc 'Update a status.' params do requires :id, type: String, desc: 'Status ID.' requires :status, type: String, desc: 'Your status.' end put ':id' do authenticate! current_user.statuses.find(params[:id]).update({ user: current_user, text: params[:status] }) end desc 'Delete a status.' params do requires :id, type: String, desc: 'Status ID.' end delete ':id' do authenticate! current_user.statuses.find(params[:id]).destroy end end end end run Twitter::API
上面的例子建立了一個簡單的Rack應用,將上面的內容放在config.ru文件中,經過以下命令啓動:安全
rackup -o 0.0.0.0
在個人環境中直接執行rackup以後,在其餘機器上沒法訪問
如今能夠訪問以下路徑:app
GET /api/statuses/public_timeline GET /api/statuses/home_timeline GET /api/statuses/:id POST /api/statuses PUT /api/statuses/:id DELETE /api/statuses/:id
全部的GET選項,Grape也會自動應答HEAD/OPTIONS選項,可是其餘路徑,只會應答OPTIONS選項。框架
若是你想在Grape中使用ActiveRecord,你要保證ActiveRecord的鏈接池處理正確。保證這一點的最簡單的方式是在安裝你的Grape應用前使用ActiveRecord的ConnectionManagement中間件:less
use ActiveRecord::ConnectionAdapters::ConnectionManagement run Twitter::API
若是使用Grape的同時想結合使用其餘Rack框架,好比Sinatra,你能夠很簡單的使用Rack::Cascade:curl
# Example config.ru require 'sinatra' require 'grape' class API < Grape::API get :hello do { hello: 'world' } end end class Web < Sinatra::Base get '/' do 'Hello world.' end end use Rack::Session::Cookie run Rack::Cascade.new [API, Web]
把全部的API文件都放置到app/api路徑下,Rails指望一個子文件夾可以匹配一個Ruby模塊,一個文件名可以匹配一個類名。在咱們的例子中,Twitter::API的路徑和文件名應該是app/api/twitter/api.rb。
修改application.rb:ide
config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb') config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
修改config/routes:post
mount Twitter::API => '/'
另外,若是使用的Rails是4.0+,而且使用了ActiveRecord默認的model層,你可能會想使用 hashie-forbidden_attributes gem包。該gem去使能model層strong_paras的安全特性,容許你使用Grape本身的參數校驗。
# Gemfile gem 'hashie-forbidden_attributes'
在一個應用內部你能夠mount多個其餘應用的API實現,它們不須要是不一樣的版本,可是多是同一接口的組件:
class Twitter::API < Grape::API mount Twitter::APIv1 mount Twitter::APIv2 end
你也能夠掛在到一個路徑上,就好像在被mount的API內部使用了prefix同樣:
class Twitter::API < Grape::API mount Twitter::APIv1 => '/v1' end
版本信息能夠經過四種方式提供:
:path、:header、:accept_version_header、:param
默認的方式是:path。
version 'v1', using: :path
經過這種方式,URL中必須提供版本信息:
curl http://localhost:9292/v1/statuses/public_timeline
version 'v1', using: :header, vendor: 'twitter'
如今,Grape僅支持以下格式的版本控制信息:
vnd.vendor-and-or-resource-v1234+format
最後的-和+之間的全部信息都會被解釋爲版本信息(上面的版本信息就是v1234)。
經過這種方式,用戶必須經過HTTP的Accept頭傳遞版本信息:
curl -H Accept:application/vnd.twitter-v1+json http://localhost:9292/statuses/public_timeline
默認的,若是沒有提供Accept頭信息,將會使用第一個匹配的版本,這種行爲和Rails中的路徑類似。爲了規避這個默認的行爲,可使用:strict選項,該選項被設置爲true時,若是沒有提供正確的Accept頭信息,會返回一個406錯誤。
當提供了一個無效的Accept頭時,若是:cascade選項設置爲false,會返回一個406錯誤。不然,若是沒有其餘的路徑匹配,Rack會返回一個404錯誤。
version 'v1', using: :accept_version_header
使用該方式時,用戶必須在HTTP頭中提供Accept-Version信息:
curl -H "Accept-Version:v1" http://localhost:9292/statuses/public_timeline
默認的,若是沒有提供Accept頭信息,將會使用第一個匹配的版本,這種行爲和Rails中的路徑類似。爲了規避這個默認的行爲,可使用:strict選項,該選項被設置爲true時,若是沒有提供正確的Accept頭信息,會返回一個406錯誤。
當提供了一個無效的Accept頭時,若是:cascade選項設置爲false,會返回一個406錯誤。不然,若是沒有其餘的路徑匹配,Rack會返回一個404錯誤。
version 'v1', using: :param
使用這種方式,用於必須在URL字符串或者請求的body中提供版本信息:
curl http://localhost:9292/statuses/public_timeline?apiver=v1
參數名稱默認是「apiver」,你也能夠經過:parameter 選項指定:
version 'v1', using: :param, parameter: 'v' curl http://localhost:9292/statuses/public_timeline?v=v1
你能夠爲API方法和名稱空間添加一個描述:
desc 'Returns your public timeline.' do detail 'more details' params API::Entities::Status.documentation success API::Entities::Entity failure [[401, 'Unauthorized', 'Entities::Error']] named 'My named route' headers XAuthToken: { description: 'Valdates your identity', required: true }, XOptionalHeader: { description: 'Not really needed', required: false } end get :public_timeline do Status.limit(20) end