grape 0.3.0 → 0.7.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.

Files changed (101) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +70 -0
  4. data/.travis.yml +7 -6
  5. data/CHANGELOG.md +134 -4
  6. data/CONTRIBUTING.md +118 -0
  7. data/Gemfile +5 -2
  8. data/README.md +551 -116
  9. data/RELEASING.md +105 -0
  10. data/Rakefile +29 -8
  11. data/UPGRADING.md +124 -0
  12. data/grape.gemspec +3 -3
  13. data/lib/grape/api.rb +207 -88
  14. data/lib/grape/cookies.rb +4 -8
  15. data/lib/grape/endpoint.rb +198 -144
  16. data/lib/grape/error_formatter/base.rb +5 -7
  17. data/lib/grape/error_formatter/json.rb +3 -5
  18. data/lib/grape/error_formatter/txt.rb +1 -3
  19. data/lib/grape/error_formatter/xml.rb +4 -6
  20. data/lib/grape/exceptions/base.rb +9 -9
  21. data/lib/grape/exceptions/incompatible_option_values.rb +10 -0
  22. data/lib/grape/exceptions/invalid_formatter.rb +1 -4
  23. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -5
  24. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -6
  25. data/lib/grape/exceptions/missing_mime_type.rb +1 -5
  26. data/lib/grape/exceptions/missing_option.rb +1 -4
  27. data/lib/grape/exceptions/missing_vendor_option.rb +1 -4
  28. data/lib/grape/exceptions/unknown_options.rb +1 -5
  29. data/lib/grape/exceptions/unknown_validator.rb +1 -3
  30. data/lib/grape/exceptions/validation.rb +13 -3
  31. data/lib/grape/exceptions/validation_errors.rb +43 -0
  32. data/lib/grape/formatter/base.rb +5 -7
  33. data/lib/grape/formatter/json.rb +0 -3
  34. data/lib/grape/formatter/serializable_hash.rb +15 -15
  35. data/lib/grape/formatter/txt.rb +0 -2
  36. data/lib/grape/formatter/xml.rb +0 -2
  37. data/lib/grape/http/request.rb +26 -0
  38. data/lib/grape/locale/en.yml +8 -5
  39. data/lib/grape/middleware/auth/base.rb +30 -0
  40. data/lib/grape/middleware/auth/basic.rb +3 -20
  41. data/lib/grape/middleware/auth/digest.rb +2 -19
  42. data/lib/grape/middleware/auth/oauth2.rb +31 -24
  43. data/lib/grape/middleware/base.rb +7 -7
  44. data/lib/grape/middleware/error.rb +36 -22
  45. data/lib/grape/middleware/filter.rb +3 -3
  46. data/lib/grape/middleware/formatter.rb +99 -61
  47. data/lib/grape/middleware/globals.rb +13 -0
  48. data/lib/grape/middleware/versioner/accept_version_header.rb +67 -0
  49. data/lib/grape/middleware/versioner/header.rb +22 -16
  50. data/lib/grape/middleware/versioner/param.rb +9 -11
  51. data/lib/grape/middleware/versioner/path.rb +10 -13
  52. data/lib/grape/middleware/versioner.rb +3 -1
  53. data/lib/grape/namespace.rb +23 -0
  54. data/lib/grape/parser/base.rb +3 -5
  55. data/lib/grape/parser/json.rb +0 -2
  56. data/lib/grape/parser/xml.rb +0 -2
  57. data/lib/grape/path.rb +70 -0
  58. data/lib/grape/route.rb +10 -6
  59. data/lib/grape/util/content_types.rb +2 -1
  60. data/lib/grape/util/deep_merge.rb +5 -5
  61. data/lib/grape/util/hash_stack.rb +13 -2
  62. data/lib/grape/validations/coerce.rb +11 -10
  63. data/lib/grape/validations/default.rb +25 -0
  64. data/lib/grape/validations/presence.rb +7 -3
  65. data/lib/grape/validations/regexp.rb +2 -5
  66. data/lib/grape/validations/values.rb +17 -0
  67. data/lib/grape/validations.rb +161 -54
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +19 -4
  70. data/spec/grape/api_spec.rb +897 -268
  71. data/spec/grape/endpoint_spec.rb +283 -66
  72. data/spec/grape/entity_spec.rb +132 -29
  73. data/spec/grape/exceptions/missing_mime_type_spec.rb +3 -9
  74. data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
  75. data/spec/grape/middleware/auth/basic_spec.rb +8 -8
  76. data/spec/grape/middleware/auth/digest_spec.rb +5 -5
  77. data/spec/grape/middleware/auth/oauth2_spec.rb +81 -36
  78. data/spec/grape/middleware/base_spec.rb +8 -13
  79. data/spec/grape/middleware/error_spec.rb +13 -17
  80. data/spec/grape/middleware/exception_spec.rb +47 -27
  81. data/spec/grape/middleware/formatter_spec.rb +103 -41
  82. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +121 -0
  83. data/spec/grape/middleware/versioner/header_spec.rb +76 -51
  84. data/spec/grape/middleware/versioner/param_spec.rb +18 -18
  85. data/spec/grape/middleware/versioner/path_spec.rb +6 -6
  86. data/spec/grape/middleware/versioner_spec.rb +5 -2
  87. data/spec/grape/path_spec.rb +229 -0
  88. data/spec/grape/util/hash_stack_spec.rb +31 -32
  89. data/spec/grape/validations/coerce_spec.rb +116 -51
  90. data/spec/grape/validations/default_spec.rb +123 -0
  91. data/spec/grape/validations/presence_spec.rb +42 -44
  92. data/spec/grape/validations/regexp_spec.rb +9 -9
  93. data/spec/grape/validations/values_spec.rb +138 -0
  94. data/spec/grape/validations/zh-CN.yml +4 -3
  95. data/spec/grape/validations_spec.rb +681 -48
  96. data/spec/shared/versioning_examples.rb +22 -6
  97. data/spec/spec_helper.rb +3 -2
  98. data/spec/support/basic_auth_encode_helpers.rb +0 -1
  99. data/spec/support/content_type_helpers.rb +11 -0
  100. data/spec/support/versioned_helpers.rb +13 -5
  101. metadata +34 -84
@@ -5,7 +5,7 @@ module Grape
5
5
  # from inside a `get`, `post`, etc.
6
6
  class Endpoint
7
7
  attr_accessor :block, :source, :options, :settings
8
- attr_reader :env, :request
8
+ attr_reader :env, :request, :headers, :params
9
9
 
10
10
  class << self
11
11
  # @api private
@@ -33,27 +33,34 @@ module Grape
33
33
  end
34
34
 
35
35
  def initialize(settings, options = {}, &block)
36
+ require_option(options, :path)
37
+ require_option(options, :method)
38
+
36
39
  @settings = settings
40
+ @options = options
41
+
42
+ @options[:path] = Array(options[:path])
43
+ @options[:path] << '/' if options[:path].empty?
44
+
45
+ @options[:method] = Array(options[:method])
46
+ @options[:route_options] ||= {}
47
+
37
48
  if block_given?
38
- method_name = [
39
- options[:method],
40
- settings.gather(:namespace).join("/"),
41
- settings.gather(:mount_path).join("/"),
42
- Array(options[:path]).join("/")
43
- ].join(" ")
44
49
  @source = block
45
50
  @block = self.class.generate_api_method(method_name, &block)
46
51
  end
47
- @options = options
48
-
49
- raise Grape::Exceptions::MissingOption.new(:path) unless options.key?(:path)
50
- options[:path] = Array(options[:path])
51
- options[:path] = ['/'] if options[:path].empty?
52
+ end
52
53
 
53
- raise Grape::Exceptions::MissingOption.new(:method) unless options.key?(:method)
54
- options[:method] = Array(options[:method])
54
+ def require_option(options, key)
55
+ raise Grape::Exceptions::MissingOption.new(key) unless options.has_key?(key)
56
+ end
55
57
 
56
- options[:route_options] ||= {}
58
+ def method_name
59
+ [options[:method],
60
+ Namespace.joined_space(settings),
61
+ settings.gather(:mount_path).join('/'),
62
+ options[:path].join('/')
63
+ ].join(" ")
57
64
  end
58
65
 
59
66
  def routes
@@ -65,15 +72,15 @@ module Grape
65
72
  endpoints.each { |e| e.mount_in(route_set) }
66
73
  else
67
74
  routes.each do |route|
68
- methods = [ route.route_method ]
69
- if ! settings[:do_not_route_head] && route.route_method == "GET"
75
+ methods = [route.route_method]
76
+ if !settings[:do_not_route_head] && route.route_method == "GET"
70
77
  methods << "HEAD"
71
78
  end
72
79
  methods.each do |method|
73
80
  route_set.add_route(self, {
74
- :path_info => route.route_compiled,
75
- :request_method => method,
76
- }, { :route_info => route })
81
+ path_info: route.route_compiled,
82
+ request_method: method,
83
+ }, route_info: route)
77
84
  end
78
85
  end
79
86
  end
@@ -88,27 +95,31 @@ module Grape
88
95
  anchor = options[:route_options][:anchor]
89
96
  anchor = anchor.nil? ? true : anchor
90
97
 
91
- requirements = options[:route_options][:requirements] || {}
98
+ endpoint_requirements = options[:route_options][:requirements] || {}
99
+ all_requirements = (settings.gather(:namespace).map(&:requirements) << endpoint_requirements)
100
+ requirements = all_requirements.reduce({}) do |base_requirements, single_requirements|
101
+ base_requirements.merge!(single_requirements)
102
+ end
92
103
 
93
104
  path = compile_path(prepared_path, anchor && !options[:app], requirements)
94
105
  regex = Rack::Mount::RegexpWithNamedGroups.new(path)
95
106
  path_params = {}
96
107
  # named parameters in the api path
97
- named_params = regex.named_captures.map { |nc| nc[0] } - [ 'version', 'format' ]
108
+ named_params = regex.named_captures.map { |nc| nc[0] } - %w{ version format }
98
109
  named_params.each { |named_param| path_params[named_param] = "" }
99
110
  # route parameters declared via desc or appended to the api declaration
100
111
  route_params = (options[:route_options][:params] || {})
101
112
  path_params.merge!(route_params)
102
113
  request_method = (method.to_s.upcase unless method == :any)
103
- routes << Route.new(options[:route_options].clone.merge({
104
- :prefix => settings[:root_prefix],
105
- :version => settings[:version] ? settings[:version].join('|') : nil,
106
- :namespace => namespace,
107
- :method => request_method,
108
- :path => prepared_path,
109
- :params => path_params,
110
- :compiled => path,
111
- })
114
+ routes << Route.new(options[:route_options].clone.merge(
115
+ prefix: settings[:root_prefix],
116
+ version: settings[:version] ? settings[:version].join('|') : nil,
117
+ namespace: namespace,
118
+ method: request_method,
119
+ path: prepared_path,
120
+ params: path_params,
121
+ compiled: path,
122
+ )
112
123
  )
113
124
  end
114
125
  end
@@ -116,28 +127,11 @@ module Grape
116
127
  end
117
128
 
118
129
  def prepare_path(path)
119
- parts = []
120
- parts << settings[:mount_path].to_s.split("/") if settings[:mount_path]
121
- parts << settings[:root_prefix].to_s.split("/") if settings[:root_prefix]
122
-
123
- uses_path_versioning = settings[:version] && settings[:version_options][:using] == :path
124
- namespace_is_empty = namespace && (namespace.to_s =~ /^\s*$/ || namespace.to_s == '/')
125
- path_is_empty = path && (path.to_s =~ /^\s*$/ || path.to_s == '/')
126
-
127
- parts << ':version' if uses_path_versioning
128
- if ! uses_path_versioning || (! namespace_is_empty || ! path_is_empty)
129
- parts << namespace.to_s if namespace
130
- parts << path.to_s if path
131
- format_suffix = '(.:format)'
132
- else
133
- format_suffix = '(/.:format)'
134
- end
135
- parts = parts.flatten.select { |part| part != '/' }
136
- Rack::Mount::Utils.normalize_path(parts.join('/') + format_suffix)
130
+ Path.prepare(path, namespace, settings)
137
131
  end
138
132
 
139
133
  def namespace
140
- Rack::Mount::Utils.normalize_path(settings.stack.map{|s| s[:namespace]}.join('/'))
134
+ @namespace ||= Namespace.joined_space_path(settings)
141
135
  end
142
136
 
143
137
  def compile_path(prepared_path, anchor = true, requirements = {})
@@ -152,56 +146,76 @@ module Grape
152
146
  end
153
147
 
154
148
  def call!(env)
149
+ extend helpers
150
+
155
151
  env['api.endpoint'] = self
156
152
  if options[:app]
157
153
  options[:app].call(env)
158
154
  else
159
155
  builder = build_middleware
160
- builder.run options[:app] || lambda{|env| self.run(env) }
156
+ builder.run options[:app] || lambda { |arg| run(arg) }
161
157
  builder.call(env)
162
158
  end
163
159
  end
164
160
 
165
- # The parameters passed into the request as
166
- # well as parsed from URL segments.
167
- def params
168
- @params ||= Hashie::Mash.new.
169
- deep_merge(request.params).
170
- deep_merge(env['rack.routing_args'] || {})
171
- end
172
-
173
161
  # A filtering method that will return a hash
174
162
  # consisting only of keys that have been declared by a
175
- # `params` statement.
163
+ # `params` statement against the current/target endpoint or parent
164
+ # namespaces
176
165
  #
177
166
  # @param params [Hash] The initial hash to filter. Usually this will just be `params`
178
- # @param options [Hash] Can pass `:include_missing` and `:stringify` options.
179
- def declared(params, options = {})
167
+ # @param options [Hash] Can pass `:include_missing`, `:stringify` and `:include_parent_namespaces`
168
+ # options. `:include_parent_namespaces` defaults to true, hence must be set to false if
169
+ # you want only to return params declared against the current/target endpoint
170
+ def declared(params, options = {}, declared_params = nil)
180
171
  options[:include_missing] = true unless options.key?(:include_missing)
172
+ options[:include_parent_namespaces] = true unless options.key?(:include_parent_namespaces)
173
+ if declared_params.nil?
174
+ declared_params = !options[:include_parent_namespaces] ? settings[:declared_params] :
175
+ settings.gather(:declared_params)
176
+ end
181
177
 
182
- unless settings[:declared_params]
178
+ unless declared_params
183
179
  raise ArgumentError, "Tried to filter for declared parameters but none exist."
184
180
  end
185
181
 
186
- settings[:declared_params].inject({}){|h,k|
187
- output_key = options[:stringify] ? k.to_s : k.to_sym
188
- if params.key?(output_key) || options[:include_missing]
189
- h[output_key] = params[k]
182
+ if params.is_a? Array
183
+ params.map do |param|
184
+ declared(param || {}, options, declared_params)
190
185
  end
191
- h
192
- }
186
+ else
187
+ declared_params.inject({}) do |hash, key|
188
+ key = { key => nil } unless key.is_a? Hash
189
+
190
+ key.each_pair do |parent, children|
191
+ output_key = options[:stringify] ? parent.to_s : parent.to_sym
192
+ if params.key?(parent) || options[:include_missing]
193
+ hash[output_key] = if children
194
+ declared(params[parent] || {}, options, Array(children))
195
+ else
196
+ params[parent]
197
+ end
198
+ end
199
+ end
200
+
201
+ hash
202
+ end
203
+ end
193
204
  end
194
205
 
195
206
  # The API version as specified in the URL.
196
- def version; env['api.version'] end
207
+ def version
208
+ env['api.version']
209
+ end
197
210
 
198
211
  # End the request and display an error to the
199
212
  # end user with the specified message.
200
213
  #
201
214
  # @param message [String] The message to display.
202
- # @param status [Integer] the HTTP Status Code. Defaults to 403.
203
- def error!(message, status=403)
204
- throw :error, :message => message, :status => status
215
+ # @param status [Integer] the HTTP Status Code. Defaults to default_error_status, 500 if not set.
216
+ def error!(message, status = nil, headers = nil)
217
+ status = settings[:default_error_status] unless status
218
+ throw :error, message: message, status: status, headers: headers
205
219
  end
206
220
 
207
221
  # Redirect to a new url.
@@ -210,7 +224,7 @@ module Grape
210
224
  # @param options [Hash] The options used when redirect.
211
225
  # :permanent, default true.
212
226
  def redirect(url, options = {})
213
- merged_options = {:permanent => false }.merge(options)
227
+ merged_options = { permanent: false }.merge(options)
214
228
  if merged_options[:permanent]
215
229
  status 301
216
230
  else
@@ -233,10 +247,10 @@ module Grape
233
247
  else
234
248
  return @status if @status
235
249
  case request.request_method.to_s.upcase
236
- when 'POST'
237
- 201
238
- else
239
- 200
250
+ when 'POST'
251
+ 201
252
+ else
253
+ 200
240
254
  end
241
255
  end
242
256
  end
@@ -251,17 +265,6 @@ module Grape
251
265
  end
252
266
  end
253
267
 
254
- # Retrieves all available request headers.
255
- def headers
256
- @headers ||= @env.dup.inject({}) { |h, (k, v)|
257
- if k.start_with? 'HTTP_'
258
- k = k[5..-1].gsub('_', '-').downcase.gsub(/^.|[-_\s]./) { |x| x.upcase }
259
- h[k] = v
260
- end
261
- h
262
- }
263
- end
264
-
265
268
  # Set response content-type
266
269
  def content_type(val)
267
270
  header('Content-Type', val)
@@ -272,7 +275,7 @@ module Grape
272
275
  # @example
273
276
  # cookies[:mycookie] = 'mycookie val'
274
277
  # cookies['mycookie-string'] = 'mycookie string val'
275
- # cookies[:more] = { :value => '123', :expires => Time.at(0) }
278
+ # cookies[:more] = { value: '123', expires: Time.at(0) }
276
279
  # cookies.delete :more
277
280
  #
278
281
  def cookies
@@ -309,32 +312,41 @@ module Grape
309
312
  #
310
313
  # get '/users/:id' do
311
314
  # present User.find(params[:id]),
312
- # :with => API::Entities::User,
313
- # :admin => current_user.admin?
315
+ # with: API::Entities::User,
316
+ # admin: current_user.admin?
314
317
  # end
315
- def present(object, options = {})
318
+ def present(*args)
319
+ options = args.count > 1 ? args.extract_options! : {}
320
+ key, object = if args.count == 2 && args.first.is_a?(Symbol)
321
+ args
322
+ else
323
+ [nil, args.first]
324
+ end
316
325
  entity_class = options.delete(:with)
317
326
 
318
- # auto-detect the entity from the first object in the collection
319
- object_instance = object.is_a?(Array) ? object.first : object
327
+ if entity_class.nil?
328
+ # entity class not explicitely defined, auto-detect from first object in the collection
329
+ object_instance = object.respond_to?(:first) ? object.first : object
320
330
 
321
- object_instance.class.ancestors.each do |potential|
322
- entity_class ||= (settings[:representations] || {})[potential]
323
- end
331
+ object_instance.class.ancestors.each do |potential|
332
+ entity_class ||= (settings[:representations] || {})[potential]
333
+ end
324
334
 
325
- entity_class ||= object_instance.class.const_get(:Entity) if object_instance.class.const_defined?(:Entity)
335
+ entity_class ||= object_instance.class.const_get(:Entity) if object_instance.class.const_defined?(:Entity) && object_instance.class.const_get(:Entity).respond_to?(:represent)
336
+ end
326
337
 
327
338
  root = options.delete(:root)
328
339
 
329
340
  representation = if entity_class
330
- embeds = {:env => env}
331
- embeds[:version] = env['api.version'] if env['api.version']
332
- entity_class.represent(object, embeds.merge(options))
333
- else
334
- object
335
- end
341
+ embeds = { env: env }
342
+ embeds[:version] = env['api.version'] if env['api.version']
343
+ entity_class.represent(object, embeds.merge(options))
344
+ else
345
+ object
346
+ end
336
347
 
337
348
  representation = { root => representation } if root
349
+ representation = (@body || {}).merge(key => representation) if key
338
350
  body representation
339
351
  end
340
352
 
@@ -350,8 +362,6 @@ module Grape
350
362
  env["rack.routing_args"][:route_info]
351
363
  end
352
364
 
353
- protected
354
-
355
365
  # Return the collection of endpoints within this endpoint.
356
366
  # This is the case when an Grape::API mounts another Grape::API.
357
367
  def endpoints
@@ -362,24 +372,39 @@ module Grape
362
372
  end
363
373
  end
364
374
 
375
+ protected
376
+
365
377
  def run(env)
366
378
  @env = env
367
379
  @header = {}
368
- @request = Rack::Request.new(@env)
369
380
 
370
- self.extend helpers
381
+ @request = Grape::Request.new(env)
382
+ @params = @request.params
383
+ @headers = @request.headers
384
+
371
385
  cookies.read(@request)
372
386
 
373
387
  run_filters befores
374
388
 
389
+ run_filters before_validations
390
+
375
391
  # Retieve validations from this namespace and all parent namespaces.
392
+ validation_errors = []
376
393
  settings.gather(:validations).each do |validator|
377
- validator.validate!(params)
394
+ begin
395
+ validator.validate!(params)
396
+ rescue Grape::Exceptions::Validation => e
397
+ validation_errors << e
398
+ end
399
+ end
400
+
401
+ if validation_errors.any?
402
+ raise Grape::Exceptions::ValidationErrors, errors: validation_errors
378
403
  end
379
404
 
380
405
  run_filters after_validations
381
406
 
382
- response_text = @block.call(self)
407
+ response_text = @block ? @block.call(self) : nil
383
408
  run_filters afters
384
409
  cookies.write(header)
385
410
 
@@ -391,54 +416,71 @@ module Grape
391
416
 
392
417
  b.use Rack::Head
393
418
  b.use Grape::Middleware::Error,
394
- :default_status => settings[:default_error_status] || 403,
395
- :rescue_all => settings[:rescue_all],
396
- :rescued_errors => aggregate_setting(:rescued_errors),
397
- :default_error_formatter => settings[:default_error_formatter],
398
- :error_formatters => settings[:error_formatters],
399
- :rescue_options => settings[:rescue_options],
400
- :rescue_handlers => merged_setting(:rescue_handlers)
401
-
402
- b.use Rack::Auth::Basic, settings[:auth][:realm], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_basic
403
- b.use Rack::Auth::Digest::MD5, settings[:auth][:realm], settings[:auth][:opaque], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_digest
404
-
405
- if settings[:version]
406
- b.use Grape::Middleware::Versioner.using(settings[:version_options][:using]), {
407
- :versions => settings[:version],
408
- :version_options => settings[:version_options],
409
- :prefix => settings[:root_prefix]
410
- }
411
- end
412
-
413
- b.use Grape::Middleware::Formatter,
414
- :format => settings[:format],
415
- :default_format => settings[:default_format] || :txt,
416
- :content_types => settings[:content_types],
417
- :formatters => settings[:formatters],
418
- :parsers => settings[:parsers]
419
+ format: settings[:format],
420
+ content_types: settings[:content_types],
421
+ default_status: settings[:default_error_status] || 500,
422
+ rescue_all: settings[:rescue_all],
423
+ default_error_formatter: settings[:default_error_formatter],
424
+ error_formatters: settings[:error_formatters],
425
+ rescue_options: settings[:rescue_options],
426
+ rescue_handlers: merged_setting(:rescue_handlers),
427
+ base_only_rescue_handlers: merged_setting(:base_only_rescue_handlers)
419
428
 
420
429
  aggregate_setting(:middleware).each do |m|
421
430
  m = m.dup
422
431
  block = m.pop if m.last.is_a?(Proc)
423
432
  if block
424
- b.use *m, &block
433
+ b.use(*m, &block)
425
434
  else
426
- b.use *m
435
+ b.use(*m)
436
+ end
437
+ end
438
+
439
+ if settings[:auth]
440
+ auth_proc = settings[:auth][:proc]
441
+ auth_proc_context = self
442
+ auth_middleware = {
443
+ http_basic: { class: Rack::Auth::Basic, args: [settings[:auth][:realm]] },
444
+ http_digest: { class: Rack::Auth::Digest::MD5, args: [settings[:auth][:realm], settings[:auth][:opaque]] }
445
+ }[settings[:auth][:type]]
446
+
447
+ # evaluate auth proc in context of endpoint
448
+ if auth_middleware
449
+ b.use auth_middleware[:class], *auth_middleware[:args] do |*args|
450
+ auth_proc_context.instance_exec(*args, &auth_proc)
451
+ end
427
452
  end
428
453
  end
429
454
 
455
+ if settings[:version]
456
+ b.use Grape::Middleware::Versioner.using(settings[:version_options][:using]),
457
+ versions: settings[:version] ? settings[:version].flatten : nil,
458
+ version_options: settings[:version_options],
459
+ prefix: settings[:root_prefix]
460
+
461
+ end
462
+
463
+ b.use Grape::Middleware::Formatter,
464
+ format: settings[:format],
465
+ default_format: settings[:default_format] || :txt,
466
+ content_types: settings[:content_types],
467
+ formatters: settings[:formatters],
468
+ parsers: settings[:parsers]
469
+
430
470
  b
431
471
  end
432
472
 
433
473
  def helpers
434
474
  m = Module.new
435
- settings.stack.each{|frame| m.send :include, frame[:helpers] if frame[:helpers]}
475
+ settings.stack.each do |frame|
476
+ m.send :include, frame[:helpers] if frame[:helpers]
477
+ end
436
478
  m
437
479
  end
438
480
 
439
481
  def aggregate_setting(key)
440
482
  settings.stack.inject([]) do |aggregate, frame|
441
- aggregate += (frame[key] || [])
483
+ aggregate + (frame[key] || [])
442
484
  end
443
485
  end
444
486
 
@@ -450,12 +492,24 @@ module Grape
450
492
 
451
493
  def run_filters(filters)
452
494
  (filters || []).each do |filter|
453
- instance_eval &filter
495
+ instance_eval(&filter)
454
496
  end
455
497
  end
456
498
 
457
- def befores; aggregate_setting(:befores) end
458
- def after_validations; aggregate_setting(:after_validations) end
459
- def afters; aggregate_setting(:afters) end
499
+ def befores
500
+ aggregate_setting(:befores)
501
+ end
502
+
503
+ def before_validations
504
+ aggregate_setting(:before_validations)
505
+ end
506
+
507
+ def after_validations
508
+ aggregate_setting(:after_validations)
509
+ end
510
+
511
+ def afters
512
+ aggregate_setting(:afters)
513
+ end
460
514
  end
461
515
  end
@@ -1,14 +1,13 @@
1
1
  module Grape
2
2
  module ErrorFormatter
3
3
  module Base
4
-
5
4
  class << self
6
-
7
5
  FORMATTERS = {
8
- :serializable_hash => Grape::ErrorFormatter::Json,
9
- :json => Grape::ErrorFormatter::Json,
10
- :txt => Grape::ErrorFormatter::Txt,
11
- :xml => Grape::ErrorFormatter::Xml
6
+ serializable_hash: Grape::ErrorFormatter::Json,
7
+ json: Grape::ErrorFormatter::Json,
8
+ jsonapi: Grape::ErrorFormatter::Json,
9
+ txt: Grape::ErrorFormatter::Txt,
10
+ xml: Grape::ErrorFormatter::Xml
12
11
  }
13
12
 
14
13
  def formatters(options)
@@ -26,7 +25,6 @@ module Grape
26
25
  spec
27
26
  end
28
27
  end
29
-
30
28
  end
31
29
  end
32
30
  end
@@ -2,15 +2,13 @@ module Grape
2
2
  module ErrorFormatter
3
3
  module Json
4
4
  class << self
5
-
6
5
  def call(message, backtrace, options = {}, env = nil)
7
- result = message.is_a?(Hash) ? message : { :error => message }
8
- if (options[:rescue_options] || {})[:backtrace] && backtrace && ! backtrace.empty?
9
- result = result.merge({ :backtrace => backtrace })
6
+ result = message.is_a?(Hash) ? message : { error: message }
7
+ if (options[:rescue_options] || {})[:backtrace] && backtrace && !backtrace.empty?
8
+ result = result.merge(backtrace: backtrace)
10
9
  end
11
10
  MultiJson.dump(result)
12
11
  end
13
-
14
12
  end
15
13
  end
16
14
  end
@@ -2,16 +2,14 @@ module Grape
2
2
  module ErrorFormatter
3
3
  module Txt
4
4
  class << self
5
-
6
5
  def call(message, backtrace, options = {}, env = nil)
7
6
  result = message.is_a?(Hash) ? MultiJson.dump(message) : message
8
- if (options[:rescue_options] || {})[:backtrace] && backtrace && ! backtrace.empty?
7
+ if (options[:rescue_options] || {})[:backtrace] && backtrace && !backtrace.empty?
9
8
  result += "\r\n "
10
9
  result += backtrace.join("\r\n ")
11
10
  end
12
11
  result
13
12
  end
14
-
15
13
  end
16
14
  end
17
15
  end
@@ -2,15 +2,13 @@ module Grape
2
2
  module ErrorFormatter
3
3
  module Xml
4
4
  class << self
5
-
6
5
  def call(message, backtrace, options = {}, env = nil)
7
- result = message.is_a?(Hash) ? message : { :message => message }
8
- if (options[:rescue_options] || {})[:backtrace] && backtrace && ! backtrace.empty?
9
- result = result.merge({ :backtrace => backtrace })
6
+ result = message.is_a?(Hash) ? message : { message: message }
7
+ if (options[:rescue_options] || {})[:backtrace] && backtrace && !backtrace.empty?
8
+ result = result.merge(backtrace: backtrace)
10
9
  end
11
- result.respond_to?(:to_xml) ? result.to_xml(:root => :error) : result.to_s
10
+ result.respond_to?(:to_xml) ? result.to_xml(root: :error) : result.to_s
12
11
  end
13
-
14
12
  end
15
13
  end
16
14
  end