Class: Grape::API::Instance

Inherits:
Object
  • Object
show all
Extended by:
DSL::Callbacks, DSL::Desc, DSL::Helpers, DSL::Logger, DSL::Middleware, DSL::RequestResponse, DSL::Routing, DSL::Settings, DSL::Validations, Middleware::Auth::DSL, Mountable
Defined in:
lib/grape/api/instance.rb

Overview

The API Instance class, is the engine behind Grape::API. Each class that inherits from this will represent a different API instance

Constant Summary collapse

Boolean =
Grape::API::Boolean
LOCK =

A class-level lock to ensure the API is not compiled by multiple threads simultaneously within the same process.

Mutex.new

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes included from DSL::Settings

#inheritable_setting

Attributes included from DSL::Routing

#endpoints

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DSL::Settings

global_setting, namespace_setting, route_setting, top_level_setting

Methods included from DSL::Desc

desc

Methods included from DSL::Validations

contract, params

Methods included from DSL::Logger

logger

Methods included from DSL::Middleware

middleware, use

Methods included from DSL::RequestResponse

content_type, content_types, default_error_formatter, default_error_status, default_format, error_formatter, format, formatter, parser, represent, rescue_from

Methods included from DSL::Routing

build_with, cascade, do_not_document!, do_not_route_head!, do_not_route_options!, given, lint!, mount, mounted, namespace, prefix, route, route_param, routes, scope, version, versions

Methods included from DSL::Helpers

helpers

Methods included from Middleware::Auth::DSL

auth, http_basic

Constructor Details

#initializeInstance

Builds the routes from the defined endpoints, effectively compiling this API into a usable form.



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/grape/api/instance.rb', line 105

def initialize
  @router = Router.new
  add_head_not_allowed_methods_and_options_methods
  self.class.endpoints.each do |endpoint|
    endpoint.mount_in(@router)
  end

  @router.compile!
  @router.freeze
  @cascade = resolve_cascade
end

Class Attribute Details

.baseObject

Returns the value of attribute base.



30
31
32
# File 'lib/grape/api/instance.rb', line 30

def base
  @base
end

.configurationObject

Returns the value of attribute configuration.



24
25
26
# File 'lib/grape/api/instance.rb', line 24

def configuration
  @configuration
end

Instance Attribute Details

#routerObject (readonly)

Returns the value of attribute router.



101
102
103
# File 'lib/grape/api/instance.rb', line 101

def router
  @router
end

Class Method Details

.base_instance?Boolean

Returns:



37
38
39
# File 'lib/grape/api/instance.rb', line 37

def base_instance?
  self == @base.base_instance
end

.call(env) ⇒ Object

This is the interface point between Rack and Grape; it accepts a request from Rack and ultimately returns an array of three values: the status, the headers, and the body. See [the rack specification] (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.



56
57
58
# File 'lib/grape/api/instance.rb', line 56

def call(env)
  compile!.call(env)
end

.change!Object

Wipe the compiled API so we can recompile after changes were made.



73
74
75
# File 'lib/grape/api/instance.rb', line 73

def change!
  @instance = nil
end

.compile!Object

Returns the compiled instance, so callers serve the one they compiled rather than re-reading @instance — change! can nil it between the two reads (see #call / #recognize_path).



63
64
65
# File 'lib/grape/api/instance.rb', line 63

def compile!
  @instance || LOCK.synchronize { @instance ||= new }
end

.recognize_path(path) ⇒ Object

see Grape::Router#recognize_path



68
69
70
# File 'lib/grape/api/instance.rb', line 68

def recognize_path(path)
  compile!.router.recognize_path(path)
end

.reset!Object

Clears all defined routes, endpoints, etc., on this API.



46
47
48
49
50
# File 'lib/grape/api/instance.rb', line 46

def reset!
  reset_endpoints!
  reset_routes!
  reset_validations!
end

.to_sObject



26
27
28
# File 'lib/grape/api/instance.rb', line 26

def to_s
  @base&.to_s || super
end

Instance Method Details

#call(env) ⇒ Object

Handle a request. See Rack documentation for what env is.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/grape/api/instance.rb', line 118

def call(env)
  status, headers, response = @router.call(env)
  unless @cascade
    # +merge!+, not +merge+: the latter is a `dup` plus a `merge!`, so the
    # Header built on this line would be allocated only to be discarded.
    # The copy stays because +headers+ can come from a mounted Rack app,
    # which is free to hand back a frozen or shared Hash that the delete
    # below must not reach into.
    headers = Grape::Util::Header.new.merge!(headers)
    headers.delete('X-Cascade')
  end

  [status, headers, response]
end

#cascade?Boolean

Some requests may return a HTTP 404 error if grape cannot find a matching route. In this case, Grape::Router 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.

Resolved in the constructor rather than per request: answering it walks the whole scope chain twice, and it reads the same settings the routes were compiled and frozen from -- changing those has to go through change!, which discards this instance.

Returns:



146
147
148
# File 'lib/grape/api/instance.rb', line 146

def cascade?
  @cascade
end