class Grape::API

The API class is the primary entry point for creating Grape APIs.Users should subclass this class in order to build an API.

Constants

Boolean
LOCK

Attributes

endpoints[R]
instance[R]
logger[W]
route_set[R]
routes[R]
settings[R]
versions[R]

Public Class Methods

after(&block) click to toggle source
# File lib/grape/api.rb, line 383
def after(&block)
  imbue(:afters, [block])
end
after_validation(&block) click to toggle source
# File lib/grape/api.rb, line 379
def after_validation(&block)
  imbue(:after_validations, [block])
end
auth(type = nil, options = {}, &block) click to toggle source

Add an authentication type to the API. Currently only `:http_basic`, `:http_digest` and `:oauth2` are supported.

# File lib/grape/api.rb, line 306
def auth(type = nil, options = {}, &block)
  if type
    set(:auth, { type: type.to_sym, proc: block }.merge(options))
  else
    settings[:auth]
  end
end
before(&block) click to toggle source
# File lib/grape/api.rb, line 371
def before(&block)
  imbue(:befores, [block])
end
before_validation(&block) click to toggle source
# File lib/grape/api.rb, line 375
def before_validation(&block)
  imbue(:before_validations, [block])
end
call(env) click to toggle source
# File lib/grape/api.rb, line 38
def call(env)
  LOCK.synchronize { compile } unless instance
  call!(env)
end
call!(env) click to toggle source
# File lib/grape/api.rb, line 43
def call!(env)
  instance.call(env)
end
cascade(value = nil) click to toggle source
# File lib/grape/api.rb, line 483
def cascade(value = nil)
  if value.nil?
    settings.key?(:cascade) ? !!settings[:cascade] : true
  else
    set(:cascade, value)
  end
end
change!() click to toggle source
# File lib/grape/api.rb, line 34
def change!
  @instance = nil
end
compile() click to toggle source
# File lib/grape/api.rb, line 30
def compile
  @instance ||= new
end
content_type(key, val) click to toggle source

Specify additional content-types, e.g.:

content_type :xls, 'application/vnd.ms-excel'
# File lib/grape/api.rb, line 173
def content_type(key, val)
  settings.imbue(:content_types, key.to_sym => val)
end
content_types() click to toggle source

All available content types.

# File lib/grape/api.rb, line 178
def content_types
  Grape::ContentTypes.content_types_for(settings[:content_types])
end
default_error_formatter(new_formatter_name = nil) click to toggle source

Specify a default error formatter.

# File lib/grape/api.rb, line 152
def default_error_formatter(new_formatter_name = nil)
  if new_formatter_name
    new_formatter = Grape::ErrorFormatter::Base.formatter_for(new_formatter_name, {})
    set(:default_error_formatter, new_formatter)
  else
    settings[:default_error_formatter]
  end
end
default_error_status(new_status = nil) click to toggle source

Specify the default status code for errors.

# File lib/grape/api.rb, line 183
def default_error_status(new_status = nil)
  new_status ? set(:default_error_status, new_status) : settings[:default_error_status]
end
default_format(new_format = nil) click to toggle source

Specify the default format for the API's serializers. May be `:json` or `:txt` (default).

# File lib/grape/api.rb, line 121
def default_format(new_format = nil)
  new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
end
delete(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 403
def delete(paths = ['/'], options = {}, &block)
  route('DELETE', paths, options, &block)
end
desc(description, options = {}) click to toggle source

Add a description to the next namespace or function.

# File lib/grape/api.rb, line 115
def desc(description, options = {})
  @last_description = options.merge(description: description)
end
do_not_route_head!() click to toggle source

Do not route HEAD requests to GET requests automatically

# File lib/grape/api.rb, line 70
def do_not_route_head!
  set(:do_not_route_head, true)
end
do_not_route_options!() click to toggle source

Do not automatically route OPTIONS

# File lib/grape/api.rb, line 75
def do_not_route_options!
  set(:do_not_route_options, true)
end
error_formatter(format, options) click to toggle source
# File lib/grape/api.rb, line 161
def error_formatter(format, options)
  if options.is_a?(Hash) && options.key?(:with)
    formatter = options[:with]
  else
    formatter = options
  end

  settings.imbue(:error_formatters, format.to_sym => formatter)
end
format(new_format = nil) click to toggle source

Specify the format for the API's serializers. May be `:json`, `:xml`, `:txt`, etc.

# File lib/grape/api.rb, line 127
def format(new_format = nil)
  if new_format
    set(:format, new_format.to_sym)
    # define the default error formatters
    set(:default_error_formatter, Grape::ErrorFormatter::Base.formatter_for(new_format, {}))
    # define a single mime type
    mime_type = content_types[new_format.to_sym]
    raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
    settings.imbue(:content_types, new_format.to_sym => mime_type)
  else
    settings[:format]
  end
end
formatter(content_type, new_formatter) click to toggle source

Specify a custom formatter for a content-type.

# File lib/grape/api.rb, line 142
def formatter(content_type, new_formatter)
  settings.imbue(:formatters, content_type.to_sym => new_formatter)
end
get(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 387
def get(paths = ['/'], options = {}, &block)
  route('GET', paths, options, &block)
end
group(space = nil, options = {}, &block)
Alias for: namespace
head(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 399
def head(paths = ['/'], options = {}, &block)
  route('HEAD', paths, options, &block)
end
helpers(new_mod = nil, &block) click to toggle source

Add helper methods that will be accessible from any endpoint within this namespace (and child namespaces).

When called without a block, all known helpers within this scope are included.

@param [Module] new_mod optional module of methods to include @param [Block] block optional block of methods to include

@example Define some helpers.

class ExampleAPI < Grape::API
  helpers do
    def current_user
      User.find_by_id(params[:token])
    end
  end
end
# File lib/grape/api.rb, line 279
def helpers(new_mod = nil, &block)
  if block_given? || new_mod
    mod = settings.peek[:helpers] || Module.new
    if new_mod
      inject_api_helpers_to_mod(new_mod) if new_mod.is_a?(Helpers)
      mod.class_eval do
        include new_mod
      end
    end
    if block_given?
      inject_api_helpers_to_mod(mod) do
        mod.class_eval(&block)
      end
    end
    set(:helpers, mod)
  else
    mod = Module.new
    settings.stack.each do |s|
      mod.send :include, s[:helpers] if s[:helpers]
    end
    change!
    mod
  end
end
http_basic(options = {}, &block) click to toggle source

Add HTTP Basic authorization to the API.

@param [Hash] options A hash of options. @option options [String] :realm “API Authorization” The HTTP Basic realm.

# File lib/grape/api.rb, line 318
def http_basic(options = {}, &block)
  options[:realm] ||= "API Authorization"
  auth :http_basic, options, &block
end
http_digest(options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 323
def http_digest(options = {}, &block)
  options[:realm] ||= "API Authorization"
  options[:opaque] ||= "secret"
  auth :http_digest, options, &block
end
imbue(key, value) click to toggle source

Add to a configuration value for this namespace.

@param key [Symbol] The key of the configuration variable. @param value [Object] The value to which to set the configuration variable.

# File lib/grape/api.rb, line 60
def imbue(key, value)
  settings.imbue(key, value)
end
logger(logger = nil) click to toggle source
# File lib/grape/api.rb, line 14
def logger(logger = nil)
  if logger
    @logger = logger
  else
    @logger ||= Logger.new($stdout)
  end
end
middleware() click to toggle source

Retrieve an array of the middleware classes and arguments that are currently applied to the application.

# File lib/grape/api.rb, line 467
def middleware
  settings.stack.inject([]) do |a, s|
    a += s[:middleware] if s[:middleware]
    a
  end
end
mount(mounts) click to toggle source
# File lib/grape/api.rb, line 329
def mount(mounts)
  mounts = { mounts => '/' } unless mounts.respond_to?(:each_pair)
  mounts.each_pair do |app, path|
    if app.respond_to?(:inherit_settings, true)
      app_settings = settings.clone
      mount_path = Rack::Mount::Utils.normalize_path([settings[:mount_path], path].compact.join("/"))
      app_settings.set :mount_path, mount_path
      app.inherit_settings(app_settings)
    end
    endpoints << Grape::Endpoint.new(
      settings.clone,
      method: :any,
      path: path,
      app: app
    )
  end
end
namespace(space = nil, options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 415
def namespace(space = nil, options = {},  &block)
  if space || block_given?
    previous_namespace_description = @namespace_description
    @namespace_description = (@namespace_description || {}).deep_merge(@last_description || {})
    @last_description = nil
    nest(block) do
      set(:namespace, Namespace.new(space, options)) if space
    end
    @namespace_description = previous_namespace_description
  else
    Namespace.joined_space_path(settings)
  end
end
Also aliased as: group, resource, resources, segment
new() click to toggle source
# File lib/grape/api.rb, line 537
def initialize
  @route_set = Rack::Mount::RouteSet.new
  add_head_not_allowed_methods_and_options_methods
  self.class.endpoints.each do |endpoint|
    endpoint.mount_in(@route_set)
  end
  @route_set.freeze
end
options(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 407
def options(paths = ['/'], options = {}, &block)
  route('OPTIONS', paths, options, &block)
end
parser(content_type, new_parser) click to toggle source

Specify a custom parser for a content-type.

# File lib/grape/api.rb, line 147
def parser(content_type, new_parser)
  settings.imbue(:parsers, content_type.to_sym => new_parser)
end
patch(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 411
def patch(paths = ['/'], options = {}, &block)
  route('PATCH', paths, options, &block)
end
post(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 391
def post(paths = ['/'], options = {}, &block)
  route('POST', paths, options, &block)
end
prefix(prefix = nil) click to toggle source

Define a root URL prefix for your entire API.

# File lib/grape/api.rb, line 65
def prefix(prefix = nil)
  prefix ? set(:root_prefix, prefix) : settings[:root_prefix]
end
put(paths = ['/'], options = {}, &block) click to toggle source
# File lib/grape/api.rb, line 395
def put(paths = ['/'], options = {}, &block)
  route('PUT', paths, options, &block)
end
represent(model_class, options) click to toggle source

Allows you to specify a default representation entity for a class. This allows you to map your models to their respective entities once and then simply call `present` with the model.

@example

class ExampleAPI < Grape::API
  represent User, with: Entity::User

  get '/me' do
    present current_user # with: Entity::User is assumed
  end
end

Note that Grape will automatically go up the class ancestry to try to find a representing entity, so if you, for example, define an entity to represent `Object` then all presented objects will bubble up and utilize the entity provided on that `represent` call.

@param model_class [Class] The model class that will be represented. @option options [Class] :with The entity class that will represent the model.

# File lib/grape/api.rb, line 255
def represent(model_class, options)
  raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with] && options[:with].is_a?(Class)
  imbue(:representations, model_class => options[:with])
end
rescue_from(*args, &block) click to toggle source

Allows you to rescue certain exceptions that occur to return a grape error rather than raising all the way to the server level.

@example Rescue from custom exceptions

class ExampleAPI < Grape::API
  class CustomError < StandardError; end

  rescue_from CustomError
end

@overload rescue_from(*exception_classes, options = {})

@param [Array] exception_classes A list of classes that you want to rescue, or
  the symbol :all to rescue from all exceptions.
@param [Block] block Execution block to handle the given exception.
@param [Hash] options Options for the rescue usage.
@option options [Boolean] :backtrace Include a backtrace in the rescue response.
@option options [Boolean] :rescue_subclasses Also rescue subclasses of exception classes
@param [Proc] handler Execution proc to handle the given exception as an
  alternative to passing a block
# File lib/grape/api.rb, line 207
def rescue_from(*args, &block)
  if args.last.is_a?(Proc)
    handler = args.pop
  elsif block_given?
    handler = block
  end

  options = args.last.is_a?(Hash) ? args.pop : {}
  handler ||= proc { options[:with] } if options.key?(:with)

  if args.include?(:all)
    set(:rescue_all, true)
    imbue :all_rescue_handler, handler
  else
    handler_type =
      case options[:rescue_subclasses]
      when nil, true
        :rescue_handlers
      else
        :base_only_rescue_handlers
      end

    imbue handler_type, Hash[args.map { |arg| [arg, handler] }]
  end

  imbue(:rescue_options, options)
end
reset!() click to toggle source
# File lib/grape/api.rb, line 22
def reset!
  @settings  = Grape::Util::HashStack.new
  @route_set = Rack::Mount::RouteSet.new
  @endpoints = []
  @routes = nil
  reset_validations!
end
resource(space = nil, options = {}, &block)
Alias for: namespace
resources(space = nil, options = {}, &block)
Alias for: namespace
route(methods, paths = ['/'], route_options = {}, &block) click to toggle source

Defines a route that will be recognized by the Grape API.

@param methods [HTTP Verb] One or more HTTP verbs that are accepted by this route. Set to `:any` if you want any verb to be accepted. @param paths [String] One or more strings representing the URL segment(s) for this route.

@example Defining a basic route.

class MyAPI < Grape::API
  route(:any, '/hello') do
    {hello: 'world'}
  end
end
# File lib/grape/api.rb, line 359
def route(methods, paths = ['/'], route_options = {}, &block)
  endpoint_options = {
    method: methods,
    path: paths,
    route_options: (@namespace_description || {}).deep_merge(@last_description || {}).deep_merge(route_options || {})
  }
  endpoints << Grape::Endpoint.new(settings.clone, endpoint_options, &block)

  @last_description = nil
  reset_validations!
end
route_param(param, options = {}, &block) click to toggle source

Thie method allows you to quickly define a parameter route segment in your API.

@param param [Symbol] The name of the parameter you wish to declare. @option options [Regexp] You may supply a regular expression that the declared parameter must meet.

# File lib/grape/api.rb, line 434
def route_param(param, options = {}, &block)
  options = options.dup
  options[:requirements] = { param.to_sym => options[:requirements] } if options[:requirements].is_a?(Regexp)
  namespace(":#{param}", options, &block)
end
scope(name = nil, &block) click to toggle source

Create a scope without affecting the URL.

@param name [Symbol] Purely placebo, just allows to to name the scope to make the code more readable.

# File lib/grape/api.rb, line 448
def scope(name = nil, &block)
  nest(block)
end
segment(space = nil, options = {}, &block)
Alias for: namespace
set(key, value) click to toggle source

Set a configuration value for this namespace.

@param key [Symbol] The key of the configuration variable. @param value [Object] The value to which to set the configuration variable.

# File lib/grape/api.rb, line 51
def set(key, value)
  settings[key.to_sym] = value
end
use(middleware_class, *args, &block) click to toggle source

Apply a custom middleware to the API. Applies to the current namespace and any children, but not parents.

@param middleware_class [Class] The class of the middleware you'd like

to inject.
# File lib/grape/api.rb, line 458
def use(middleware_class, *args, &block)
  arr = [middleware_class, *args]
  arr << block if block_given?
  imbue(:middleware, [arr])
end
version(*args, &block) click to toggle source

Specify an API version.

@example API with legacy support.

class MyAPI < Grape::API
  version 'v2'

  get '/main' do
    {some: 'data'}
  end

  version 'v1' do
    get '/main' do
      {legacy: 'data'}
    end
  end
end
# File lib/grape/api.rb, line 96
def version(*args, &block)
  if args.any?
    options = args.pop if args.last.is_a? Hash
    options ||= {}
    options = { using: :path }.merge(options)

    raise Grape::Exceptions::MissingVendorOption.new if options[:using] == :header && !options.key?(:vendor)

    @versions = versions | args
    nest(block) do
      set(:version, args)
      set(:version_options, options)
    end
  end

  @versions.last unless @versions.nil?
end

Protected Class Methods

inherit_settings(other_stack) click to toggle source
# File lib/grape/api.rb, line 522
def inherit_settings(other_stack)
  settings.prepend other_stack
  endpoints.each do |e|
    e.settings.prepend(other_stack)
    e.options[:app].inherit_settings(other_stack) if e.options[:app].respond_to?(:inherit_settings, true)
  end
end
inherited(subclass) click to toggle source
# File lib/grape/api.rb, line 517
def inherited(subclass)
  subclass.reset!
  subclass.logger = logger.clone
end
inject_api_helpers_to_mod(mod) { || ... } click to toggle source
# File lib/grape/api.rb, line 530
def inject_api_helpers_to_mod(mod, &block)
  mod.extend(Helpers)
  yield if block_given?
  mod.api_changed(self)
end
nest(*blocks, &block) click to toggle source

Execute first the provided block, then each of the block passed in. Allows for simple 'before' setups of settings stack pushes.

# File lib/grape/api.rb, line 504
def nest(*blocks, &block)
  blocks.reject! { |b| b.nil? }
  if blocks.any?
    settings.push  # create a new context to eval the follow
    instance_eval(&block) if block_given?
    blocks.each { |b| instance_eval(&b) }
    settings.pop # when finished, we pop the context
    reset_validations!
  else
    instance_eval(&block)
  end
end
prepare_routes() click to toggle source
# File lib/grape/api.rb, line 493
def prepare_routes
  routes = []
  endpoints.each do |endpoint|
    routes.concat(endpoint.routes)
  end
  routes
end

Public Instance Methods

call(env) click to toggle source
# File lib/grape/api.rb, line 546
def call(env)
  status, headers, body = @route_set.call(env)
  headers.delete('X-Cascade') unless cascade?
  [status, headers, body]
end
cascade?() click to toggle source

Some requests may return a HTTP 404 error if grape cannot find a matching route. In this case, Rack::Mount adds a X-Cascade header to the response and sets it to 'pass', indicating to grape's parents they should keep looking for a matching route on other resources.

In some applications (e.g. mounting grape on rails), one might need to trap errors from reaching upstream. This is effectivelly done by unsetting X-Cascade. Default :cascade is true.

# File lib/grape/api.rb, line 560
def cascade?
  return !!self.class.settings[:cascade] if self.class.settings.key?(:cascade)
  return !!self.class.settings[:version_options][:cascade] if self.class.settings[:version_options] && self.class.settings[:version_options].key?(:cascade)
  true
end

Private Instance Methods

add_head_not_allowed_methods_and_options_methods() click to toggle source

For every resource add a 'OPTIONS' route that returns an HTTP 204 response with a list of HTTP methods that can be called. Also add a route that will return an HTTP 405 response for any HTTP method that the resource cannot handle.

# File lib/grape/api.rb, line 574
def add_head_not_allowed_methods_and_options_methods
  methods_per_path = {}
  self.class.endpoints.each do |endpoint|
    routes = endpoint.routes
    routes.each do |route|
      methods_per_path[route.route_path] ||= []
      methods_per_path[route.route_path] << route.route_method
    end
  end

  # The paths we collected are prepared (cf. Path#prepare), so they
  # contain already versioning information when using path versioning.
  # Disable versioning so adding a route won't prepend versioning
  # informations again.
  without_versioning do
    methods_per_path.each do |path, methods|
      allowed_methods = methods.dup
      unless self.class.settings[:do_not_route_head]
        allowed_methods |= ['HEAD'] if allowed_methods.include?('GET')
      end

      allow_header = (['OPTIONS'] | allowed_methods).join(', ')
      unless self.class.settings[:do_not_route_options]
        unless allowed_methods.include?('OPTIONS')
          self.class.options(path, {}) do
            header 'Allow', allow_header
            status 204
            ''
          end
        end
      end

      not_allowed_methods = %w(GET PUT POST DELETE PATCH HEAD) - allowed_methods
      not_allowed_methods << 'OPTIONS' if self.class.settings[:do_not_route_options]
      self.class.route(not_allowed_methods, path) do
        header 'Allow', allow_header
        status 405
        ''
      end
    end
  end
end
without_versioning() { || ... } click to toggle source
# File lib/grape/api.rb, line 617
def without_versioning(&block)
  self.class.settings.push(version: nil, version_options: nil)
  yield
  self.class.settings.pop
end