Grape簡介

什麼是Grape

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

上面的例子建立了一個簡單的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選項。框架

脫離Rails使用ActiveRecord

若是你想在Grape中使用ActiveRecord,你要保證ActiveRecord的鏈接池處理正確。保證這一點的最簡單的方式是在安裝你的Grape應用前使用ActiveRecord的ConnectionManagement中間件:less

use ActiveRecord::ConnectionAdapters::ConnectionManagement

run Twitter::API

結合Sinatra(或者其餘框架)

若是使用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]

Rails

把全部的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'

Modules

在一個應用內部你能夠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。

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錯誤。

Accept-Version Header

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錯誤。

Param

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
  • detail
    更詳細的描述。
  • params
    直接從一個Entity定義參數。
  • success: (former entity) The Entity to be used to present by default this route
  • failure: (former http_codes) A definition of the used failure HTTP Codes and Entities
  • named: A helper to give a route a name and find it with this name in the documentation Hash
  • headers: A definition of the used Headers
相關文章
相關標籤/搜索