grape 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- data/.gitignore +13 -1
- data/.rspec +1 -1
- data/.travis.yml +1 -0
- data/Gemfile +10 -0
- data/Guardfile +15 -0
- data/README.markdown +472 -67
- data/grape.gemspec +4 -4
- data/lib/grape.rb +17 -5
- data/lib/grape/api.rb +227 -124
- data/lib/grape/cookies.rb +41 -0
- data/lib/grape/endpoint.rb +256 -27
- data/lib/grape/entity.rb +227 -0
- data/lib/grape/middleware/auth/oauth2.rb +1 -2
- data/lib/grape/middleware/base.rb +59 -6
- data/lib/grape/middleware/error.rb +15 -6
- data/lib/grape/middleware/filter.rb +17 -0
- data/lib/grape/middleware/formatter.rb +25 -31
- data/lib/grape/middleware/versioner.rb +20 -20
- data/lib/grape/middleware/versioner/header.rb +59 -0
- data/lib/grape/middleware/versioner/path.rb +42 -0
- data/lib/grape/route.rb +23 -0
- data/lib/grape/util/hash_stack.rb +100 -0
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +651 -162
- data/spec/grape/endpoint_spec.rb +216 -18
- data/spec/grape/entity_spec.rb +320 -0
- data/spec/grape/middleware/auth/basic_spec.rb +2 -2
- data/spec/grape/middleware/auth/digest_spec.rb +4 -6
- data/spec/grape/middleware/exception_spec.rb +1 -0
- data/spec/grape/middleware/formatter_spec.rb +81 -27
- data/spec/grape/middleware/versioner/header_spec.rb +148 -0
- data/spec/grape/middleware/versioner/path_spec.rb +40 -0
- data/spec/grape/middleware/versioner_spec.rb +6 -34
- data/spec/grape/util/hash_stack_spec.rb +133 -0
- data/spec/shared/versioning_examples.rb +77 -0
- data/spec/spec_helper.rb +11 -3
- data/spec/support/basic_auth_encode_helpers.rb +4 -0
- data/spec/support/rack_patch.rb +25 -0
- data/spec/support/versioned_helpers.rb +34 -0
- metadata +140 -241
- data/.yardoc/checksums +0 -13
- data/.yardoc/objects/Grape.dat +0 -0
- data/.yardoc/objects/Grape/API.dat +0 -0
- data/.yardoc/objects/Grape/API/auth_c.dat +0 -0
- data/.yardoc/objects/Grape/API/build_endpoint_c.dat +0 -0
- data/.yardoc/objects/Grape/API/call_c.dat +0 -0
- data/.yardoc/objects/Grape/API/compile_path_c.dat +0 -0
- data/.yardoc/objects/Grape/API/default_format_c.dat +0 -0
- data/.yardoc/objects/Grape/API/delete_c.dat +0 -0
- data/.yardoc/objects/Grape/API/get_c.dat +0 -0
- data/.yardoc/objects/Grape/API/group_c.dat +0 -0
- data/.yardoc/objects/Grape/API/head_c.dat +0 -0
- data/.yardoc/objects/Grape/API/helpers_c.dat +0 -0
- data/.yardoc/objects/Grape/API/http_basic_c.dat +0 -0
- data/.yardoc/objects/Grape/API/inherited_c.dat +0 -0
- data/.yardoc/objects/Grape/API/logger_c.dat +0 -0
- data/.yardoc/objects/Grape/API/namespace_c.dat +0 -0
- data/.yardoc/objects/Grape/API/nest_c.dat +0 -0
- data/.yardoc/objects/Grape/API/post_c.dat +0 -0
- data/.yardoc/objects/Grape/API/prefix_c.dat +0 -0
- data/.yardoc/objects/Grape/API/put_c.dat +0 -0
- data/.yardoc/objects/Grape/API/reset_21_c.dat +0 -0
- data/.yardoc/objects/Grape/API/resource_c.dat +0 -0
- data/.yardoc/objects/Grape/API/resources_c.dat +0 -0
- data/.yardoc/objects/Grape/API/route_c.dat +0 -0
- data/.yardoc/objects/Grape/API/route_set_c.dat +0 -0
- data/.yardoc/objects/Grape/API/scope_c.dat +0 -0
- data/.yardoc/objects/Grape/API/set_c.dat +0 -0
- data/.yardoc/objects/Grape/API/settings_c.dat +0 -0
- data/.yardoc/objects/Grape/API/settings_stack_c.dat +0 -0
- data/.yardoc/objects/Grape/API/version_c.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/block_3D_c.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/block_c.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/call_c.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/call_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/env_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/error_21_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/generate_c.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/header_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/params_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/request_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/status_i.dat +0 -0
- data/.yardoc/objects/Grape/Endpoint/version_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/Basic.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/Basic/authenticator_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/Basic/basic_request_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/Basic/before_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/Basic/credentials_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/Basic/initialize_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2/before_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2/default_options_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2/error_out_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2/parse_authorization_header_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2/token_class_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Auth/OAuth2/verify_token_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/after_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/app_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/before_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/call_21_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/call_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/default_options_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/env_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/initialize_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/options_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/request_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Base/response_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Error.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Error/call_21_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Error/error_response_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/CONTENT_TYPES.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/after_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/before_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/content_types_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/default_options_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/encode_json_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/encode_txt_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/format_from_extension_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/format_from_header_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/headers_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/mime_array_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Formatter/mime_types_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Prefixer.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Prefixer/before_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Prefixer/prefix_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Versioner.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Versioner/before_i.dat +0 -0
- data/.yardoc/objects/Grape/Middleware/Versioner/default_options_i.dat +0 -0
- data/.yardoc/objects/Grape/MiddlewareStack.dat +0 -0
- data/.yardoc/objects/Grape/MiddlewareStack/initialize_i.dat +0 -0
- data/.yardoc/objects/Grape/MiddlewareStack/stack_i.dat +0 -0
- data/.yardoc/objects/Grape/MiddlewareStack/to_app_i.dat +0 -0
- data/.yardoc/objects/Grape/MiddlewareStack/use_i.dat +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -2
- data/Gemfile.lock +0 -52
- data/autotest/discover.rb +0 -1
data/grape.gemspec
CHANGED
@@ -10,22 +10,22 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.homepage = "https://github.com/intridea/grape"
|
11
11
|
s.summary = %q{A simple Ruby framework for building REST-like APIs.}
|
12
12
|
s.description = %q{A Ruby framework for rapid API development with great conventions.}
|
13
|
+
s.license = "MIT"
|
13
14
|
|
14
15
|
s.rubyforge_project = "grape"
|
15
16
|
|
16
17
|
s.add_runtime_dependency 'rack'
|
17
18
|
s.add_runtime_dependency 'rack-mount'
|
18
|
-
s.add_runtime_dependency 'rack-jsonp'
|
19
|
+
# s.add_runtime_dependency 'rack-jsonp'
|
19
20
|
s.add_runtime_dependency 'multi_json'
|
20
21
|
s.add_runtime_dependency 'multi_xml'
|
22
|
+
s.add_runtime_dependency 'hashie', '~> 1.2'
|
21
23
|
|
22
24
|
s.add_development_dependency 'rake'
|
23
25
|
s.add_development_dependency 'maruku'
|
24
26
|
s.add_development_dependency 'yard'
|
25
27
|
s.add_development_dependency 'rack-test'
|
26
|
-
s.add_development_dependency 'rspec', '~> 2.
|
27
|
-
s.add_development_dependency 'json_pure'
|
28
|
-
s.add_development_dependency 'ZenTest'
|
28
|
+
s.add_development_dependency 'rspec', '~> 2.9'
|
29
29
|
s.add_development_dependency 'bundler'
|
30
30
|
|
31
31
|
s.files = `git ls-files`.split("\n")
|
data/lib/grape.rb
CHANGED
@@ -2,23 +2,35 @@ require 'rack'
|
|
2
2
|
require 'rack/builder'
|
3
3
|
|
4
4
|
module Grape
|
5
|
-
autoload :API,
|
6
|
-
autoload :Endpoint,
|
5
|
+
autoload :API, 'grape/api'
|
6
|
+
autoload :Endpoint, 'grape/endpoint'
|
7
7
|
autoload :MiddlewareStack, 'grape/middleware_stack'
|
8
|
-
autoload :Client,
|
9
|
-
|
8
|
+
autoload :Client, 'grape/client'
|
9
|
+
autoload :Route, 'grape/route'
|
10
|
+
autoload :Entity, 'grape/entity'
|
11
|
+
autoload :Cookies, 'grape/cookies'
|
12
|
+
|
10
13
|
module Middleware
|
11
14
|
autoload :Base, 'grape/middleware/base'
|
12
15
|
autoload :Prefixer, 'grape/middleware/prefixer'
|
13
16
|
autoload :Versioner, 'grape/middleware/versioner'
|
14
17
|
autoload :Formatter, 'grape/middleware/formatter'
|
15
18
|
autoload :Error, 'grape/middleware/error'
|
16
|
-
|
19
|
+
|
17
20
|
module Auth
|
18
21
|
autoload :OAuth2, 'grape/middleware/auth/oauth2'
|
19
22
|
autoload :Basic, 'grape/middleware/auth/basic'
|
20
23
|
autoload :Digest, 'grape/middleware/auth/digest'
|
21
24
|
end
|
25
|
+
|
26
|
+
module Versioner
|
27
|
+
autoload :Path, 'grape/middleware/versioner/path'
|
28
|
+
autoload :Header, 'grape/middleware/versioner/header'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module Util
|
33
|
+
autoload :HashStack, 'grape/util/hash_stack'
|
22
34
|
end
|
23
35
|
end
|
24
36
|
|
data/lib/grape/api.rb
CHANGED
@@ -5,47 +5,69 @@ require 'logger'
|
|
5
5
|
|
6
6
|
module Grape
|
7
7
|
# The API class is the primary entry point for
|
8
|
-
# creating Grape APIs.
|
8
|
+
# creating Grape APIs.Users should subclass this
|
9
9
|
# class in order to build an API.
|
10
10
|
class API
|
11
11
|
class << self
|
12
12
|
attr_reader :route_set
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
attr_reader :versions
|
14
|
+
attr_reader :routes
|
15
|
+
attr_reader :settings
|
16
|
+
attr_writer :logger
|
17
|
+
attr_reader :endpoints
|
18
|
+
attr_reader :mountings
|
19
|
+
attr_reader :instance
|
20
|
+
|
21
|
+
def logger(logger = nil)
|
22
|
+
if logger
|
23
|
+
@logger = logger
|
24
|
+
else
|
25
|
+
@logger ||= Logger.new($stdout)
|
26
|
+
end
|
16
27
|
end
|
17
|
-
|
28
|
+
|
18
29
|
def reset!
|
19
|
-
@settings
|
30
|
+
@settings = Grape::Util::HashStack.new
|
20
31
|
@route_set = Rack::Mount::RouteSet.new
|
21
|
-
@
|
32
|
+
@endpoints = []
|
33
|
+
@mountings = []
|
34
|
+
@routes = nil
|
22
35
|
end
|
23
|
-
|
36
|
+
|
37
|
+
def compile
|
38
|
+
@instance = self.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def change!
|
42
|
+
@instance = nil
|
43
|
+
end
|
44
|
+
|
24
45
|
def call(env)
|
25
|
-
|
26
|
-
|
46
|
+
compile unless instance
|
47
|
+
call!(env)
|
27
48
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# in the order pushed.
|
32
|
-
def settings
|
33
|
-
@settings.inject({}){|f,h| f.merge!(h); f}
|
49
|
+
|
50
|
+
def call!(env)
|
51
|
+
instance.call(env)
|
34
52
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
53
|
+
|
54
|
+
# Set a configuration value for this namespace.
|
55
|
+
#
|
56
|
+
# @param key [Symbol] The key of the configuration variable.
|
57
|
+
# @param value [Object] The value to which to set the configuration variable.
|
58
|
+
def set(key, value)
|
59
|
+
settings[key.to_sym] = value
|
38
60
|
end
|
39
|
-
|
40
|
-
#
|
61
|
+
|
62
|
+
# Add to a configuration value for this
|
41
63
|
# namespace.
|
42
64
|
#
|
43
65
|
# @param key [Symbol] The key of the configuration variable.
|
44
66
|
# @param value [Object] The value to which to set the configuration variable.
|
45
|
-
def
|
46
|
-
|
67
|
+
def imbue(key, value)
|
68
|
+
settings.imbue(key, value)
|
47
69
|
end
|
48
|
-
|
70
|
+
|
49
71
|
# Define a root URL prefix for your entire
|
50
72
|
# API.
|
51
73
|
def prefix(prefix = nil)
|
@@ -57,11 +79,11 @@ module Grape
|
|
57
79
|
# @example API with legacy support.
|
58
80
|
# class MyAPI < Grape::API
|
59
81
|
# version 'v2'
|
60
|
-
#
|
82
|
+
#
|
61
83
|
# get '/main' do
|
62
84
|
# {:some => 'data'}
|
63
85
|
# end
|
64
|
-
#
|
86
|
+
#
|
65
87
|
# version 'v1' do
|
66
88
|
# get '/main' do
|
67
89
|
# {:legacy => 'data'}
|
@@ -69,23 +91,48 @@ module Grape
|
|
69
91
|
# end
|
70
92
|
# end
|
71
93
|
#
|
72
|
-
def version(*
|
73
|
-
|
94
|
+
def version(*args, &block)
|
95
|
+
if args.any?
|
96
|
+
options = args.pop if args.last.is_a? Hash
|
97
|
+
options ||= {}
|
98
|
+
options = {:using => :path}.merge!(options)
|
99
|
+
@versions = versions | args
|
100
|
+
nest(block) do
|
101
|
+
set(:version, args)
|
102
|
+
set(:version_options, options)
|
103
|
+
end
|
104
|
+
end
|
74
105
|
end
|
75
|
-
|
76
|
-
#
|
77
|
-
|
78
|
-
|
106
|
+
|
107
|
+
# Add a description to the next namespace or function.
|
108
|
+
def desc(description, options = {})
|
109
|
+
@last_description = options.merge(:description => description)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Specify the default format for the API's serializers.
|
113
|
+
# May be `:json` or `:txt` (default).
|
79
114
|
def default_format(new_format = nil)
|
80
115
|
new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
|
81
116
|
end
|
82
117
|
|
118
|
+
# Specify the format for the API's serializers.
|
119
|
+
# May be `:json` or `:txt`.
|
120
|
+
def format(new_format = nil)
|
121
|
+
new_format ? set(:format, new_format.to_sym) : settings[:format]
|
122
|
+
end
|
123
|
+
|
83
124
|
# Specify the format for error messages.
|
84
125
|
# May be `:json` or `:txt` (default).
|
85
126
|
def error_format(new_format = nil)
|
86
127
|
new_format ? set(:error_format, new_format.to_sym) : settings[:error_format]
|
87
128
|
end
|
88
129
|
|
130
|
+
# Specify additional content-types, e.g.:
|
131
|
+
# content_type :xls, 'application/vnd.ms-excel'
|
132
|
+
def content_type(key, val)
|
133
|
+
settings.imbue(:content_types, key.to_sym => val)
|
134
|
+
end
|
135
|
+
|
89
136
|
# Specify the default status code for errors.
|
90
137
|
def default_error_status(new_status = nil)
|
91
138
|
new_status ? set(:default_error_status, new_status) : settings[:default_error_status]
|
@@ -105,17 +152,54 @@ module Grape
|
|
105
152
|
# @overload rescue_from(*exception_classes, options = {})
|
106
153
|
# @param [Array] exception_classes A list of classes that you want to rescue, or
|
107
154
|
# the symbol :all to rescue from all exceptions.
|
155
|
+
# @param [Block] block Execution block to handle the given exception.
|
108
156
|
# @param [Hash] options Options for the rescue usage.
|
109
157
|
# @option options [Boolean] :backtrace Include a backtrace in the rescue response.
|
110
|
-
def rescue_from(*args)
|
111
|
-
|
158
|
+
def rescue_from(*args, &block)
|
159
|
+
if block_given?
|
160
|
+
args.each do |arg|
|
161
|
+
imbue(:rescue_handlers, { arg => block })
|
162
|
+
end
|
163
|
+
end
|
164
|
+
imbue(:rescue_options, args.pop) if args.last.is_a?(Hash)
|
112
165
|
set(:rescue_all, true) and return if args.include?(:all)
|
113
|
-
|
166
|
+
imbue(:rescued_errors, args)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Allows you to specify a default representation entity for a
|
170
|
+
# class. This allows you to map your models to their respective
|
171
|
+
# entities once and then simply call `present` with the model.
|
172
|
+
#
|
173
|
+
# @example
|
174
|
+
# class ExampleAPI < Grape::API
|
175
|
+
# represent User, :with => Entity::User
|
176
|
+
#
|
177
|
+
# get '/me' do
|
178
|
+
# present current_user # :with => Entity::User is assumed
|
179
|
+
# end
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# Note that Grape will automatically go up the class ancestry to
|
183
|
+
# try to find a representing entity, so if you, for example, define
|
184
|
+
# an entity to represent `Object` then all presented objects will
|
185
|
+
# bubble up and utilize the entity provided on that `represent` call.
|
186
|
+
#
|
187
|
+
# @param model_class [Class] The model class that will be represented.
|
188
|
+
# @option options [Class] :with The entity class that will represent the model.
|
189
|
+
def represent(model_class, options)
|
190
|
+
raise ArgumentError, "You must specify an entity class in the :with option." unless options[:with] && options[:with].is_a?(Class)
|
191
|
+
imbue(:representations, model_class => options[:with])
|
114
192
|
end
|
115
193
|
|
116
194
|
# Add helper methods that will be accessible from any
|
117
195
|
# endpoint within this namespace (and child namespaces).
|
118
196
|
#
|
197
|
+
# When called without a block, all known helpers within this scope
|
198
|
+
# are included.
|
199
|
+
#
|
200
|
+
# @param mod [Module] optional module of methods to include
|
201
|
+
# @param &block [Block] optional block of methods to include
|
202
|
+
#
|
119
203
|
# @example Define some helpers.
|
120
204
|
# class ExampleAPI < Grape::API
|
121
205
|
# helpers do
|
@@ -124,20 +208,21 @@ module Grape
|
|
124
208
|
# end
|
125
209
|
# end
|
126
210
|
# end
|
127
|
-
def helpers(&block)
|
128
|
-
if block_given?
|
129
|
-
|
130
|
-
|
131
|
-
set(:helpers,
|
211
|
+
def helpers(mod = nil, &block)
|
212
|
+
if block_given? || mod
|
213
|
+
mod ||= settings.peek[:helpers] || Module.new
|
214
|
+
mod.class_eval &block if block_given?
|
215
|
+
set(:helpers, mod)
|
132
216
|
else
|
133
|
-
|
134
|
-
|
135
|
-
|
217
|
+
mod = Module.new
|
218
|
+
settings.stack.each do |s|
|
219
|
+
mod.send :include, s[:helpers] if s[:helpers]
|
136
220
|
end
|
137
|
-
|
221
|
+
change!
|
222
|
+
mod
|
138
223
|
end
|
139
224
|
end
|
140
|
-
|
225
|
+
|
141
226
|
# Add an authentication type to the API. Currently
|
142
227
|
# only `:http_basic`, `:http_digest` and `:oauth2` are supported.
|
143
228
|
def auth(type = nil, options = {}, &block)
|
@@ -147,7 +232,7 @@ module Grape
|
|
147
232
|
settings[:auth]
|
148
233
|
end
|
149
234
|
end
|
150
|
-
|
235
|
+
|
151
236
|
# Add HTTP Basic authorization to the API.
|
152
237
|
#
|
153
238
|
# @param [Hash] options A hash of options.
|
@@ -159,10 +244,25 @@ module Grape
|
|
159
244
|
|
160
245
|
def http_digest(options = {}, &block)
|
161
246
|
options[:realm] ||= "API Authorization"
|
162
|
-
|
247
|
+
options[:opaque] ||= "secret"
|
163
248
|
auth :http_digest, options, &block
|
164
249
|
end
|
165
|
-
|
250
|
+
|
251
|
+
def mount(mounts)
|
252
|
+
mounts = {mounts => '/'} unless mounts.respond_to?(:each_pair)
|
253
|
+
mounts.each_pair do |app, path|
|
254
|
+
if app.respond_to?(:inherit_settings)
|
255
|
+
app.inherit_settings(settings.clone)
|
256
|
+
end
|
257
|
+
|
258
|
+
endpoints << Grape::Endpoint.new(settings.clone,
|
259
|
+
:method => :any,
|
260
|
+
:path => path,
|
261
|
+
:app => app
|
262
|
+
)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
166
266
|
# Defines a route that will be recognized
|
167
267
|
# by the Grape API.
|
168
268
|
#
|
@@ -175,47 +275,49 @@ module Grape
|
|
175
275
|
# {:hello => 'world'}
|
176
276
|
# end
|
177
277
|
# end
|
178
|
-
def route(methods, paths, &block)
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
methods.each do |method|
|
187
|
-
paths.each do |path|
|
188
|
-
path = Rack::Mount::Strexp.compile(compile_path(path), options, ['/'], true)
|
189
|
-
route_set.add_route(endpoint,
|
190
|
-
:path_info => path,
|
191
|
-
:request_method => (method.to_s.upcase unless method == :any)
|
192
|
-
)
|
193
|
-
end
|
194
|
-
end
|
278
|
+
def route(methods, paths = ['/'], route_options = {}, &block)
|
279
|
+
endpoint_options = {
|
280
|
+
:method => methods,
|
281
|
+
:path => paths,
|
282
|
+
:route_options => (route_options || {}).merge(@last_description || {})
|
283
|
+
}
|
284
|
+
endpoints << Grape::Endpoint.new(settings.clone, endpoint_options, &block)
|
285
|
+
@last_description = nil
|
195
286
|
end
|
196
|
-
|
197
|
-
def
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
def
|
202
|
-
|
287
|
+
|
288
|
+
def before(&block)
|
289
|
+
imbue(:befores, [block])
|
290
|
+
end
|
291
|
+
|
292
|
+
def after(&block)
|
293
|
+
imbue(:afters, [block])
|
294
|
+
end
|
295
|
+
|
296
|
+
def get(paths = ['/'], options = {}, &block); route('GET', paths, options, &block) end
|
297
|
+
def post(paths = ['/'], options = {}, &block); route('POST', paths, options, &block) end
|
298
|
+
def put(paths = ['/'], options = {}, &block); route('PUT', paths, options, &block) end
|
299
|
+
def head(paths = ['/'], options = {}, &block); route('HEAD', paths, options, &block) end
|
300
|
+
def delete(paths = ['/'], options = {}, &block); route('DELETE', paths, options, &block) end
|
301
|
+
def options(paths = ['/'], options = {}, &block); route('OPTIONS', paths, options, &block) end
|
302
|
+
def patch(paths = ['/'], options = {}, &block); route('PATCH', paths, options, &block) end
|
303
|
+
|
203
304
|
def namespace(space = nil, &block)
|
204
305
|
if space || block_given?
|
205
306
|
nest(block) do
|
206
307
|
set(:namespace, space.to_s) if space
|
207
308
|
end
|
208
309
|
else
|
209
|
-
Rack::Mount::Utils.normalize_path(
|
310
|
+
Rack::Mount::Utils.normalize_path(settings.stack.map{|s| s[:namespace]}.join('/'))
|
210
311
|
end
|
211
312
|
end
|
212
|
-
|
313
|
+
|
213
314
|
alias_method :group, :namespace
|
214
315
|
alias_method :resource, :namespace
|
215
316
|
alias_method :resources, :namespace
|
216
|
-
|
317
|
+
alias_method :segment, :namespace
|
318
|
+
|
217
319
|
# Create a scope without affecting the URL.
|
218
|
-
#
|
320
|
+
#
|
219
321
|
# @param name [Symbol] Purely placebo, just allows to to name the scope to make the code more readable.
|
220
322
|
def scope(name = nil, &block)
|
221
323
|
nest(block)
|
@@ -225,77 +327,78 @@ module Grape
|
|
225
327
|
# to the current namespace and any children, but
|
226
328
|
# not parents.
|
227
329
|
#
|
228
|
-
# @param middleware_class [Class] The class of the middleware you'd like
|
229
|
-
|
230
|
-
|
231
|
-
|
330
|
+
# @param middleware_class [Class] The class of the middleware you'd like
|
331
|
+
# to inject.
|
332
|
+
def use(middleware_class, *args, &block)
|
333
|
+
arr = [middleware_class, *args]
|
334
|
+
arr << block if block_given?
|
335
|
+
imbue(:middleware, [arr])
|
232
336
|
end
|
233
337
|
|
234
338
|
# Retrieve an array of the middleware classes
|
235
339
|
# and arguments that are currently applied to the
|
236
340
|
# application.
|
237
341
|
def middleware
|
238
|
-
|
342
|
+
settings.stack.inject([]){|a,s| a += s[:middleware] if s[:middleware]; a}
|
343
|
+
end
|
344
|
+
|
345
|
+
# An array of API routes.
|
346
|
+
def routes
|
347
|
+
@routes ||= prepare_routes
|
348
|
+
end
|
349
|
+
|
350
|
+
def versions
|
351
|
+
@versions ||= []
|
239
352
|
end
|
240
353
|
|
241
354
|
protected
|
242
|
-
|
355
|
+
|
356
|
+
def prepare_routes
|
357
|
+
routes = []
|
358
|
+
endpoints.each do |endpoint|
|
359
|
+
routes.concat(endpoint.routes)
|
360
|
+
end
|
361
|
+
routes
|
362
|
+
end
|
363
|
+
|
243
364
|
# Execute first the provided block, then each of the
|
244
365
|
# block passed in. Allows for simple 'before' setups
|
245
366
|
# of settings stack pushes.
|
246
367
|
def nest(*blocks, &block)
|
247
368
|
blocks.reject!{|b| b.nil?}
|
248
369
|
if blocks.any?
|
249
|
-
|
370
|
+
settings.push # create a new context to eval the follow
|
250
371
|
instance_eval &block if block_given?
|
251
372
|
blocks.each{|b| instance_eval &b}
|
252
|
-
|
373
|
+
settings.pop # when finished, we pop the context
|
253
374
|
else
|
254
375
|
instance_eval &block
|
255
376
|
end
|
256
377
|
end
|
257
|
-
|
258
|
-
|
259
|
-
b = Rack::Builder.new
|
260
|
-
b.use Grape::Middleware::Error,
|
261
|
-
:default_status => settings[:default_error_status] || 403,
|
262
|
-
:rescue_all => settings[:rescue_all],
|
263
|
-
:rescued_errors => settings[:rescued_errors],
|
264
|
-
:format => settings[:error_format] || :txt,
|
265
|
-
:rescue_options => settings[:rescue_options]
|
266
|
-
b.use Rack::Auth::Basic, settings[:auth][:realm], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_basic
|
267
|
-
b.use Rack::Auth::Digest::MD5, settings[:auth][:realm], settings[:auth][:opaque], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_digest
|
268
|
-
b.use Grape::Middleware::Prefixer, :prefix => prefix if prefix
|
269
|
-
b.use Grape::Middleware::Versioner, :versions => (version if version.is_a?(Array)) if version
|
270
|
-
b.use Grape::Middleware::Formatter, :default_format => default_format || :json
|
271
|
-
middleware.each{|m| b.use *m }
|
272
|
-
|
273
|
-
endpoint = Grape::Endpoint.generate(&block)
|
274
|
-
endpoint.send :include, helpers
|
275
|
-
b.run endpoint
|
276
|
-
|
277
|
-
b.to_app
|
278
|
-
end
|
279
|
-
|
280
|
-
def inherited(subclass)
|
378
|
+
|
379
|
+
def inherited(subclass)
|
281
380
|
subclass.reset!
|
381
|
+
subclass.logger = logger.clone
|
282
382
|
end
|
283
|
-
|
284
|
-
def
|
285
|
-
|
383
|
+
|
384
|
+
def inherit_settings(other_stack)
|
385
|
+
settings.prepend other_stack
|
386
|
+
endpoints.each{|e| e.settings.prepend(other_stack)}
|
286
387
|
end
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
388
|
+
end
|
389
|
+
|
390
|
+
def initialize
|
391
|
+
@route_set = Rack::Mount::RouteSet.new
|
392
|
+
self.class.endpoints.each do |endpoint|
|
393
|
+
endpoint.mount_in(@route_set)
|
394
|
+
end
|
395
|
+
@route_set.freeze
|
396
|
+
end
|
397
|
+
|
398
|
+
def call(env)
|
399
|
+
@route_set.call(env)
|
400
|
+
end
|
401
|
+
|
402
|
+
reset!
|
300
403
|
end
|
301
404
|
end
|