grape 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +76 -161
- data/UPGRADING.md +106 -0
- data/grape.gemspec +2 -2
- data/lib/grape/api/instance.rb +1 -1
- data/lib/grape/api.rb +1 -1
- data/lib/grape/declared_params_handler.rb +3 -3
- data/lib/grape/dsl/declared.rb +1 -1
- data/lib/grape/dsl/desc.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +9 -9
- data/lib/grape/dsl/parameters.rb +14 -14
- data/lib/grape/dsl/routing.rb +8 -8
- data/lib/grape/endpoint.rb +45 -50
- data/lib/grape/error_formatter/base.rb +2 -2
- data/lib/grape/exceptions/base.rb +18 -44
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_message_body.rb +1 -1
- data/lib/grape/exceptions/invalid_version_header.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/method_not_allowed.rb +1 -1
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/request_error.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +1 -1
- data/lib/grape/exceptions/unknown_parameter.rb +1 -1
- data/lib/grape/exceptions/unknown_params_builder.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/validation.rb +7 -4
- data/lib/grape/exceptions/validation_errors.rb +13 -7
- data/lib/grape/locale/en.yml +0 -5
- data/lib/grape/middleware/auth/base.rb +2 -0
- data/lib/grape/middleware/base.rb +2 -4
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +1 -1
- data/lib/grape/middleware/versioner/accept_version_header.rb +1 -1
- data/lib/grape/request.rb +2 -10
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router.rb +4 -2
- data/lib/grape/util/api_description.rb +1 -1
- data/lib/grape/util/deep_freeze.rb +35 -0
- data/lib/grape/util/inheritable_setting.rb +1 -1
- data/lib/grape/util/media_type.rb +1 -1
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +33 -18
- data/lib/grape/validations/contract_scope.rb +1 -7
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/param_scope_tracker.rb +57 -0
- data/lib/grape/validations/params_scope.rb +111 -107
- data/lib/grape/validations/single_attribute_iterator.rb +2 -2
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
- data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
- data/lib/grape/validations/validators/base.rb +95 -18
- data/lib/grape/validations/validators/coerce_validator.rb +15 -35
- data/lib/grape/validations/validators/contract_scope_validator.rb +10 -8
- data/lib/grape/validations/validators/default_validator.rb +12 -18
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +13 -4
- data/lib/grape/validations/validators/length_validator.rb +21 -22
- data/lib/grape/validations/validators/multiple_params_base.rb +5 -5
- data/lib/grape/validations/validators/mutually_exclusive_validator.rb +3 -1
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +8 -10
- data/lib/grape/validations/validators/same_as_validator.rb +6 -15
- data/lib/grape/validations/validators/values_validator.rb +29 -21
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +18 -1
- metadata +12 -14
- data/lib/grape/exceptions/conflicting_types.rb +0 -11
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/invalid_parameters.rb +0 -11
- data/lib/grape/exceptions/too_deep_parameters.rb +0 -11
- data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
- data/lib/grape/validations/validator_factory.rb +0 -15
data/lib/grape/dsl/routing.rb
CHANGED
|
@@ -60,7 +60,7 @@ module Grape
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
@versions
|
|
63
|
+
@versions&.last
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# Define a root URL prefix for your entire API.
|
|
@@ -136,8 +136,8 @@ module Grape
|
|
|
136
136
|
endpoints << Grape::Endpoint.new(
|
|
137
137
|
in_setting,
|
|
138
138
|
method: :any,
|
|
139
|
-
path
|
|
140
|
-
app
|
|
139
|
+
path:,
|
|
140
|
+
app:,
|
|
141
141
|
route_options: { anchor: false },
|
|
142
142
|
forward_match: !app.respond_to?(:inheritable_setting),
|
|
143
143
|
for: self
|
|
@@ -167,13 +167,13 @@ module Grape
|
|
|
167
167
|
|
|
168
168
|
new_endpoint = Grape::Endpoint.new(
|
|
169
169
|
inheritable_setting,
|
|
170
|
-
method
|
|
170
|
+
method:,
|
|
171
171
|
path: paths,
|
|
172
172
|
for: self,
|
|
173
173
|
route_options: all_route_options,
|
|
174
174
|
&
|
|
175
175
|
)
|
|
176
|
-
endpoints << new_endpoint unless endpoints.
|
|
176
|
+
endpoints << new_endpoint unless endpoints.include?(new_endpoint)
|
|
177
177
|
|
|
178
178
|
inheritable_setting.route_end
|
|
179
179
|
reset_validations!
|
|
@@ -203,7 +203,7 @@ module Grape
|
|
|
203
203
|
|
|
204
204
|
within_namespace do
|
|
205
205
|
nest(block) do
|
|
206
|
-
inheritable_setting.namespace_stackable[:namespace] = Grape::Namespace.new(space, requirements
|
|
206
|
+
inheritable_setting.namespace_stackable[:namespace] = Grape::Namespace.new(space, requirements:, **options) if space
|
|
207
207
|
end
|
|
208
208
|
end
|
|
209
209
|
end
|
|
@@ -223,14 +223,14 @@ module Grape
|
|
|
223
223
|
#
|
|
224
224
|
# @param param [Symbol] The name of the parameter you wish to declare.
|
|
225
225
|
# @option options [Regexp] You may supply a regular expression that the declared parameter must meet.
|
|
226
|
-
def route_param(param, requirements: nil, type: nil,
|
|
226
|
+
def route_param(param, requirements: nil, type: nil, **, &)
|
|
227
227
|
requirements = { param.to_sym => requirements } if requirements.is_a?(Regexp)
|
|
228
228
|
|
|
229
229
|
Grape::Validations::ParamsScope.new(api: self) do
|
|
230
230
|
requires param, type: type
|
|
231
231
|
end if type
|
|
232
232
|
|
|
233
|
-
namespace(":#{param}", requirements
|
|
233
|
+
namespace(":#{param}", requirements:, **, &)
|
|
234
234
|
end
|
|
235
235
|
|
|
236
236
|
# @return array of defined versions
|
data/lib/grape/endpoint.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Grape
|
|
|
11
11
|
include Grape::DSL::Headers
|
|
12
12
|
include Grape::DSL::InsideRoute
|
|
13
13
|
|
|
14
|
-
attr_reader :env, :request, :source, :options
|
|
14
|
+
attr_reader :env, :request, :source, :options, :endpoints
|
|
15
15
|
|
|
16
16
|
def_delegators :request, :params, :headers, :cookies
|
|
17
17
|
def_delegator :cookies, :response_cookies
|
|
@@ -23,8 +23,10 @@ module Grape
|
|
|
23
23
|
return @before_each unless block
|
|
24
24
|
|
|
25
25
|
@before_each << block
|
|
26
|
-
|
|
26
|
+
elsif new_setup
|
|
27
27
|
@before_each = [new_setup]
|
|
28
|
+
else
|
|
29
|
+
@before_each.clear
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -64,20 +66,21 @@ module Grape
|
|
|
64
66
|
inheritable_setting.route[:declared_params] = inheritable_setting.namespace_stackable[:declared_params].flatten
|
|
65
67
|
inheritable_setting.route[:saved_validations] = inheritable_setting.namespace_stackable[:validations]
|
|
66
68
|
|
|
67
|
-
inheritable_setting.namespace_stackable[:representations]
|
|
68
|
-
inheritable_setting.namespace_inheritable[:default_error_status]
|
|
69
|
+
inheritable_setting.namespace_stackable[:representations] ||= []
|
|
70
|
+
inheritable_setting.namespace_inheritable[:default_error_status] ||= 500
|
|
69
71
|
|
|
70
72
|
@options = options
|
|
71
73
|
|
|
72
|
-
@options[:path] = Array(options[:path])
|
|
73
|
-
@options[:path] << '/' if options[:path].empty?
|
|
74
|
-
@options[:method] = Array(options[:method])
|
|
74
|
+
@options[:path] = Array(@options[:path])
|
|
75
|
+
@options[:path] << '/' if @options[:path].empty?
|
|
76
|
+
@options[:method] = Array(@options[:method])
|
|
75
77
|
|
|
76
78
|
@status = nil
|
|
77
79
|
@stream = nil
|
|
78
80
|
@body = nil
|
|
79
81
|
@source = self.class.block_to_unbound_method(block)
|
|
80
82
|
@before_filter_passed = false
|
|
83
|
+
@endpoints = @options[:app].endpoints if @options[:app].respond_to?(:endpoints)
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
# Update our settings from a given set of stackable parameters. Used when
|
|
@@ -92,7 +95,7 @@ module Grape
|
|
|
92
95
|
end
|
|
93
96
|
|
|
94
97
|
def routes
|
|
95
|
-
@routes ||= endpoints&.
|
|
98
|
+
@routes ||= endpoints&.flat_map(&:routes) || to_routes
|
|
96
99
|
end
|
|
97
100
|
|
|
98
101
|
def reset_routes!
|
|
@@ -111,7 +114,7 @@ module Grape
|
|
|
111
114
|
compile!
|
|
112
115
|
routes.each do |route|
|
|
113
116
|
router.append(route.apply(self))
|
|
114
|
-
next
|
|
117
|
+
next if inheritable_setting.namespace_inheritable[:do_not_route_head] || route.request_method != Rack::GET
|
|
115
118
|
|
|
116
119
|
route.dup.then do |head_route|
|
|
117
120
|
head_route.convert_to_head_request!
|
|
@@ -136,15 +139,12 @@ module Grape
|
|
|
136
139
|
@app.call(env)
|
|
137
140
|
end
|
|
138
141
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def equals?(endpoint)
|
|
146
|
-
(options == endpoint.options) && (inheritable_setting.to_hash == endpoint.inheritable_setting.to_hash)
|
|
142
|
+
def ==(other)
|
|
143
|
+
other.is_a?(self.class) &&
|
|
144
|
+
options == other.options &&
|
|
145
|
+
inheritable_setting.to_hash == other.inheritable_setting.to_hash
|
|
147
146
|
end
|
|
147
|
+
alias eql? ==
|
|
148
148
|
|
|
149
149
|
# The purpose of this override is solely for stripping internals when an error occurs while calling
|
|
150
150
|
# an endpoint through an api. See https://github.com/ruby-grape/grape/issues/2398
|
|
@@ -158,7 +158,7 @@ module Grape
|
|
|
158
158
|
protected
|
|
159
159
|
|
|
160
160
|
def run
|
|
161
|
-
ActiveSupport::Notifications.instrument('endpoint_run.grape', endpoint: self, env:
|
|
161
|
+
ActiveSupport::Notifications.instrument('endpoint_run.grape', endpoint: self, env:) do
|
|
162
162
|
@request = Grape::Request.new(env, build_params_with: inheritable_setting.namespace_inheritable[:build_params_with])
|
|
163
163
|
begin
|
|
164
164
|
self.class.run_before_each(self)
|
|
@@ -174,7 +174,7 @@ module Grape
|
|
|
174
174
|
status 204
|
|
175
175
|
else
|
|
176
176
|
run_filters before_validations, :before_validation
|
|
177
|
-
run_validators
|
|
177
|
+
run_validators(request:)
|
|
178
178
|
run_filters after_validations, :after_validation
|
|
179
179
|
response_object = execute
|
|
180
180
|
end
|
|
@@ -196,35 +196,40 @@ module Grape
|
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
def execute
|
|
199
|
-
return unless
|
|
199
|
+
return unless source
|
|
200
200
|
|
|
201
201
|
ActiveSupport::Notifications.instrument('endpoint_render.grape', endpoint: self) do
|
|
202
|
-
|
|
202
|
+
source.bind_call(self)
|
|
203
203
|
end
|
|
204
204
|
end
|
|
205
205
|
|
|
206
|
-
def run_validators(
|
|
206
|
+
def run_validators(request:)
|
|
207
|
+
validators = inheritable_setting.route[:saved_validations]
|
|
208
|
+
return if validators.empty?
|
|
209
|
+
|
|
207
210
|
validation_errors = []
|
|
208
211
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
validator
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
Grape::Validations::ParamScopeTracker.track do
|
|
213
|
+
ActiveSupport::Notifications.instrument('endpoint_run_validators.grape', endpoint: self, validators:, request:) do
|
|
214
|
+
validators.each do |validator|
|
|
215
|
+
validator.validate(request)
|
|
216
|
+
rescue Grape::Exceptions::Validation => e
|
|
217
|
+
validation_errors << e
|
|
218
|
+
break if validator.fail_fast?
|
|
219
|
+
rescue Grape::Exceptions::ValidationArrayErrors => e
|
|
220
|
+
validation_errors.concat e.errors
|
|
221
|
+
break if validator.fail_fast?
|
|
222
|
+
end
|
|
218
223
|
end
|
|
219
224
|
end
|
|
220
225
|
|
|
221
|
-
|
|
226
|
+
raise(Grape::Exceptions::ValidationErrors.new(errors: validation_errors, headers: header)) if validation_errors.any?
|
|
222
227
|
end
|
|
223
228
|
|
|
224
229
|
def run_filters(filters, type = :other)
|
|
225
230
|
return unless filters
|
|
226
231
|
|
|
227
|
-
ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', endpoint: self, filters
|
|
232
|
+
ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', endpoint: self, filters:, type:) do
|
|
228
233
|
filters.each { |filter| instance_eval(&filter) }
|
|
229
234
|
end
|
|
230
235
|
end
|
|
@@ -235,16 +240,6 @@ module Grape
|
|
|
235
240
|
end
|
|
236
241
|
end
|
|
237
242
|
|
|
238
|
-
def validations
|
|
239
|
-
saved_validations = inheritable_setting.route[:saved_validations]
|
|
240
|
-
return if saved_validations.nil?
|
|
241
|
-
return enum_for(:validations) unless block_given?
|
|
242
|
-
|
|
243
|
-
saved_validations.each do |saved_validation|
|
|
244
|
-
yield Grape::Validations::ValidatorFactory.create_validator(saved_validation)
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
243
|
def options?
|
|
249
244
|
options[:options_route_enabled] &&
|
|
250
245
|
env[Rack::REQUEST_METHOD] == Rack::OPTIONS
|
|
@@ -284,7 +279,7 @@ module Grape
|
|
|
284
279
|
|
|
285
280
|
def prepare_default_route_attributes(route_options)
|
|
286
281
|
{
|
|
287
|
-
namespace
|
|
282
|
+
namespace:,
|
|
288
283
|
version: prepare_version(inheritable_setting.namespace_inheritable[:version]),
|
|
289
284
|
requirements: prepare_routes_requirements(route_options[:requirements]),
|
|
290
285
|
prefix: inheritable_setting.namespace_inheritable[:root_prefix],
|
|
@@ -321,15 +316,15 @@ module Grape
|
|
|
321
316
|
stack.use Rack::Head
|
|
322
317
|
stack.use Rack::Lint if lint?
|
|
323
318
|
stack.use Grape::Middleware::Error,
|
|
324
|
-
format
|
|
325
|
-
content_types
|
|
319
|
+
format:,
|
|
320
|
+
content_types:,
|
|
326
321
|
default_status: inheritable_setting.namespace_inheritable[:default_error_status],
|
|
327
322
|
rescue_all: inheritable_setting.namespace_inheritable[:rescue_all],
|
|
328
323
|
rescue_grape_exceptions: inheritable_setting.namespace_inheritable[:rescue_grape_exceptions],
|
|
329
324
|
default_error_formatter: inheritable_setting.namespace_inheritable[:default_error_formatter],
|
|
330
325
|
error_formatters: inheritable_setting.namespace_stackable_with_hash(:error_formatters),
|
|
331
326
|
rescue_options: inheritable_setting.namespace_stackable_with_hash(:rescue_options),
|
|
332
|
-
rescue_handlers
|
|
327
|
+
rescue_handlers:,
|
|
333
328
|
base_only_rescue_handlers: inheritable_setting.namespace_stackable_with_hash(:base_only_rescue_handlers),
|
|
334
329
|
all_rescue_handler: inheritable_setting.namespace_inheritable[:all_rescue_handler],
|
|
335
330
|
grape_exceptions_rescue_handler: inheritable_setting.namespace_inheritable[:grape_exceptions_rescue_handler]
|
|
@@ -345,9 +340,9 @@ module Grape
|
|
|
345
340
|
end
|
|
346
341
|
|
|
347
342
|
stack.use Grape::Middleware::Formatter,
|
|
348
|
-
format
|
|
343
|
+
format:,
|
|
349
344
|
default_format: inheritable_setting.namespace_inheritable[:default_format] || :txt,
|
|
350
|
-
content_types
|
|
345
|
+
content_types:,
|
|
351
346
|
formatters: inheritable_setting.namespace_stackable_with_hash(:formatters),
|
|
352
347
|
parsers: inheritable_setting.namespace_stackable_with_hash(:parsers)
|
|
353
348
|
|
|
@@ -365,7 +360,7 @@ module Grape
|
|
|
365
360
|
|
|
366
361
|
def build_response_cookies
|
|
367
362
|
response_cookies do |name, value|
|
|
368
|
-
cookie_value = value.is_a?(Hash) ? value : { value:
|
|
363
|
+
cookie_value = value.is_a?(Hash) ? value : { value: }
|
|
369
364
|
Rack::Utils.set_cookie_header! header, name, cookie_value
|
|
370
365
|
end
|
|
371
366
|
end
|
|
@@ -40,7 +40,7 @@ module Grape
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
if presenter
|
|
43
|
-
embeds = { env:
|
|
43
|
+
embeds = { env: }
|
|
44
44
|
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
|
45
45
|
presented_message = presenter.represent(presented_message, embeds).serializable_hash
|
|
46
46
|
end
|
|
@@ -51,7 +51,7 @@ module Grape
|
|
|
51
51
|
def wrap_message(message)
|
|
52
52
|
return message if message.is_a?(Hash)
|
|
53
53
|
|
|
54
|
-
{ message:
|
|
54
|
+
{ message: }
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def format_structured_message(_structured_message)
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Exceptions
|
|
5
5
|
class Base < StandardError
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
include Grape::Util::Translation
|
|
7
|
+
|
|
8
|
+
MESSAGE_STEPS = %w[problem summary resolution].to_h { |s| [s, s.capitalize] }.freeze
|
|
9
9
|
|
|
10
10
|
attr_reader :status, :headers
|
|
11
11
|
|
|
@@ -20,55 +20,29 @@ module Grape
|
|
|
20
20
|
__send__ index
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
private
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# if BASE_ATTRIBUTES_KEY.key respond to a Hash, means it may have problem , summary and resolution
|
|
28
|
-
def compose_message(key, **attributes)
|
|
29
|
-
short_message = translate_message(key, attributes)
|
|
25
|
+
def compose_message(key, **)
|
|
26
|
+
short_message = translate_message(key, **)
|
|
30
27
|
return short_message unless short_message.is_a?(Hash)
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def each_steps(key, attributes)
|
|
38
|
-
return enum_for(:each_steps, key, attributes) unless block_given?
|
|
39
|
-
|
|
40
|
-
yield 'Problem', translate_message(:"#{key}.problem", attributes)
|
|
41
|
-
yield 'Summary', translate_message(:"#{key}.summary", attributes)
|
|
42
|
-
yield 'Resolution', translate_message(:"#{key}.resolution", attributes)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def translate_attributes(keys, options = {})
|
|
46
|
-
keys.map do |key|
|
|
47
|
-
translate("#{BASE_ATTRIBUTES_KEY}.#{key}", options.merge(default: key.to_s))
|
|
48
|
-
end.join(', ')
|
|
29
|
+
MESSAGE_STEPS.filter_map do |step, label|
|
|
30
|
+
detail = translate_message(:"#{key}.#{step}", **)
|
|
31
|
+
"\n#{label}:\n #{detail}" if detail.present?
|
|
32
|
+
end.join
|
|
49
33
|
end
|
|
50
34
|
|
|
51
|
-
def translate_message(
|
|
52
|
-
case
|
|
35
|
+
def translate_message(translation_key, **)
|
|
36
|
+
case translation_key
|
|
53
37
|
when Symbol
|
|
54
|
-
translate(
|
|
38
|
+
translate(translation_key, **)
|
|
39
|
+
when Hash
|
|
40
|
+
translation_key => { key:, **opts }
|
|
41
|
+
translate(key, **opts)
|
|
55
42
|
when Proc
|
|
56
|
-
|
|
57
|
-
else
|
|
58
|
-
key
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def translate(key, options)
|
|
63
|
-
message = ::I18n.translate(key, **options)
|
|
64
|
-
message.presence || fallback_message(key, options)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def fallback_message(key, options)
|
|
68
|
-
if ::I18n.enforce_available_locales && !::I18n.available_locales.include?(FALLBACK_LOCALE)
|
|
69
|
-
key
|
|
43
|
+
translation_key.call
|
|
70
44
|
else
|
|
71
|
-
|
|
45
|
+
translation_key
|
|
72
46
|
end
|
|
73
47
|
end
|
|
74
48
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class IncompatibleOptionValues < Base
|
|
6
6
|
def initialize(option1, value1, option2, value2)
|
|
7
|
-
super(message: compose_message(:incompatible_option_values, option1
|
|
7
|
+
super(message: compose_message(:incompatible_option_values, option1:, value1:, option2:, value2:))
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class InvalidAcceptHeader < Base
|
|
6
6
|
def initialize(message, headers)
|
|
7
|
-
super(message: compose_message(:invalid_accept_header, message:
|
|
7
|
+
super(message: compose_message(:invalid_accept_header, message:), status: 406, headers:)
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class InvalidFormatter < Base
|
|
6
6
|
def initialize(klass, to_format)
|
|
7
|
-
super(message: compose_message(:invalid_formatter, klass
|
|
7
|
+
super(message: compose_message(:invalid_formatter, klass:, to_format:))
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class InvalidMessageBody < Base
|
|
6
6
|
def initialize(body_format)
|
|
7
|
-
super(message: compose_message(:invalid_message_body, body_format:
|
|
7
|
+
super(message: compose_message(:invalid_message_body, body_format:), status: 400)
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class InvalidVersionHeader < Base
|
|
6
6
|
def initialize(message, headers)
|
|
7
|
-
super(message: compose_message(:invalid_version_header, message:
|
|
7
|
+
super(message: compose_message(:invalid_version_header, message:), status: 406, headers:)
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class InvalidVersionerOption < Base
|
|
6
6
|
def initialize(strategy)
|
|
7
|
-
super(message: compose_message(:invalid_versioner_option, strategy:
|
|
7
|
+
super(message: compose_message(:invalid_versioner_option, strategy:))
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class UnknownParamsBuilder < Base
|
|
6
6
|
def initialize(params_builder_type)
|
|
7
|
-
super(message: compose_message(:unknown_params_builder, params_builder_type:
|
|
7
|
+
super(message: compose_message(:unknown_params_builder, params_builder_type:))
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
|
4
4
|
module Exceptions
|
|
5
5
|
class UnknownValidator < Base
|
|
6
6
|
def initialize(validator_type)
|
|
7
|
-
super(message: compose_message(:unknown_validator, validator_type:
|
|
7
|
+
super(message: compose_message(:unknown_validator, validator_type:))
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -3,16 +3,19 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Exceptions
|
|
5
5
|
class Validation < Base
|
|
6
|
-
|
|
6
|
+
attr_reader :params, :message_key
|
|
7
7
|
|
|
8
8
|
def initialize(params:, message: nil, status: nil, headers: nil)
|
|
9
|
-
@params = params
|
|
9
|
+
@params = Array(params)
|
|
10
10
|
if message
|
|
11
|
-
@message_key =
|
|
11
|
+
@message_key = case message
|
|
12
|
+
when Symbol then message
|
|
13
|
+
when Hash then message[:key]
|
|
14
|
+
end
|
|
12
15
|
message = translate_message(message)
|
|
13
16
|
end
|
|
14
17
|
|
|
15
|
-
super(status
|
|
18
|
+
super(status:, message:, headers:)
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
# Remove all the unnecessary stuff from Grape::Exceptions::Base like status
|
|
@@ -3,16 +3,13 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Exceptions
|
|
5
5
|
class ValidationErrors < Base
|
|
6
|
-
ERRORS_FORMAT_KEY = 'grape.errors.format'
|
|
7
|
-
DEFAULT_ERRORS_FORMAT = '%<attributes>s %<message>s'
|
|
8
|
-
|
|
9
6
|
include Enumerable
|
|
10
7
|
|
|
11
8
|
attr_reader :errors
|
|
12
9
|
|
|
13
10
|
def initialize(errors: [], headers: {})
|
|
14
11
|
@errors = errors.group_by(&:params)
|
|
15
|
-
super(message: full_messages.join(', '), status: 400, headers:
|
|
12
|
+
super(message: full_messages.join(', '), status: 400, headers:)
|
|
16
13
|
end
|
|
17
14
|
|
|
18
15
|
def each
|
|
@@ -38,9 +35,10 @@ module Grape
|
|
|
38
35
|
|
|
39
36
|
def full_messages
|
|
40
37
|
messages = map do |attributes, error|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
translate(
|
|
39
|
+
:format,
|
|
40
|
+
scope: 'grape.errors',
|
|
41
|
+
default: '%<attributes>s %<message>s',
|
|
44
42
|
attributes: translate_attributes(attributes),
|
|
45
43
|
message: error.message
|
|
46
44
|
)
|
|
@@ -48,6 +46,14 @@ module Grape
|
|
|
48
46
|
messages.uniq!
|
|
49
47
|
messages
|
|
50
48
|
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def translate_attributes(keys)
|
|
53
|
+
keys.map do |key|
|
|
54
|
+
translate(key, scope: 'grape.errors.attributes', default: key.to_s)
|
|
55
|
+
end.join(', ')
|
|
56
|
+
end
|
|
51
57
|
end
|
|
52
58
|
end
|
|
53
59
|
end
|
data/lib/grape/locale/en.yml
CHANGED
|
@@ -8,8 +8,6 @@ en:
|
|
|
8
8
|
at_least_one: 'are missing, at least one parameter must be provided'
|
|
9
9
|
blank: 'is empty'
|
|
10
10
|
coerce: 'is invalid'
|
|
11
|
-
conflicting_types: 'query params contains conflicting types'
|
|
12
|
-
empty_message_body: 'empty message body supplied with %{body_format} content-type'
|
|
13
11
|
exactly_one: 'are missing, exactly one parameter must be provided'
|
|
14
12
|
except_values: 'has a value not allowed'
|
|
15
13
|
incompatible_option_values: '%{option1}: %{value1} is incompatible with %{option2}: %{value2}'
|
|
@@ -20,7 +18,6 @@ en:
|
|
|
20
18
|
invalid_message_body:
|
|
21
19
|
problem: 'message body does not match declared format'
|
|
22
20
|
resolution: 'when specifying %{body_format} as content-type, you must pass valid %{body_format} in the request''s ''body'' '
|
|
23
|
-
invalid_parameters: 'query params contains invalid format or byte sequence'
|
|
24
21
|
invalid_response: 'Invalid response'
|
|
25
22
|
invalid_version_header:
|
|
26
23
|
problem: 'invalid version header'
|
|
@@ -48,8 +45,6 @@ en:
|
|
|
48
45
|
presence: 'is missing'
|
|
49
46
|
regexp: 'is invalid'
|
|
50
47
|
same_as: 'is not the same as %{parameter}'
|
|
51
|
-
too_deep_parameters: 'query params are recursively nested over the specified limit (%{limit})'
|
|
52
|
-
too_many_multipart_files: 'the number of uploaded files exceeded the system''s configured limit (%{limit})'
|
|
53
48
|
unknown_auth_strategy: 'unknown auth strategy: %{strategy}'
|
|
54
49
|
unknown_options: 'unknown options: %{options}'
|
|
55
50
|
unknown_parameter: 'unknown parameter: %{param}'
|
|
@@ -6,6 +6,8 @@ module Grape
|
|
|
6
6
|
class Base < Grape::Middleware::Base
|
|
7
7
|
def initialize(app, **options)
|
|
8
8
|
super
|
|
9
|
+
return unless options.key?(:type)
|
|
10
|
+
|
|
9
11
|
@auth_strategy = Grape::Middleware::Auth::Strategies[options[:type]].tap do |auth_strategy|
|
|
10
12
|
raise Grape::Exceptions::UnknownAuthStrategy.new(strategy: options[:type]) unless auth_strategy
|
|
11
13
|
end
|
|
@@ -79,10 +79,8 @@ module Grape
|
|
|
79
79
|
|
|
80
80
|
def query_params
|
|
81
81
|
rack_request.GET
|
|
82
|
-
rescue
|
|
83
|
-
raise Grape::Exceptions::
|
|
84
|
-
rescue Rack::Utils::ParameterTypeError
|
|
85
|
-
raise Grape::Exceptions::ConflictingTypes
|
|
82
|
+
rescue *Grape::RACK_ERRORS
|
|
83
|
+
raise Grape::Exceptions::RequestError
|
|
86
84
|
end
|
|
87
85
|
|
|
88
86
|
private
|