grape 1.8.0 → 3.3.5
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 +391 -1
- data/CONTRIBUTING.md +3 -11
- data/README.md +648 -552
- data/UPGRADING.md +803 -7
- data/grape.gemspec +11 -14
- data/lib/grape/api/instance.rb +68 -158
- data/lib/grape/api.rb +71 -107
- data/lib/grape/content_types.rb +23 -11
- data/lib/grape/cookies.rb +28 -25
- data/lib/grape/declared_params_handler.rb +116 -0
- data/lib/grape/dry_types.rb +48 -6
- data/lib/grape/dsl/callbacks.rb +14 -58
- data/lib/grape/dsl/declared.rb +35 -0
- data/lib/grape/dsl/desc.rb +15 -63
- data/lib/grape/dsl/entity.rb +88 -0
- data/lib/grape/dsl/headers.rb +2 -2
- data/lib/grape/dsl/helpers.rb +83 -64
- data/lib/grape/dsl/inside_route.rb +56 -295
- data/lib/grape/dsl/logger.rb +4 -9
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +50 -82
- data/lib/grape/dsl/request_response.rb +144 -146
- data/lib/grape/dsl/rescue_options.rb +24 -0
- data/lib/grape/dsl/routing.rb +261 -186
- data/lib/grape/dsl/settings.rb +29 -135
- data/lib/grape/dsl/validations.rb +39 -32
- data/lib/grape/dsl/version_options.rb +23 -0
- data/lib/grape/endpoint/options.rb +19 -0
- data/lib/grape/endpoint.rb +277 -250
- data/lib/grape/{util/env.rb → env.rb} +1 -8
- data/lib/grape/error_formatter/base.rb +56 -21
- data/lib/grape/error_formatter/json.rb +13 -15
- data/lib/grape/error_formatter/serializable_hash.rb +7 -0
- data/lib/grape/error_formatter/txt.rb +12 -18
- data/lib/grape/error_formatter/xml.rb +3 -13
- data/lib/grape/error_formatter.rb +5 -25
- data/lib/grape/exceptions/base.rb +22 -58
- data/lib/grape/exceptions/error_response.rb +45 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/internal_server_error.rb +16 -0
- 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_group_type.rb +0 -2
- 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 +11 -0
- data/lib/grape/exceptions/unknown_parameter.rb +1 -1
- data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
- data/lib/grape/exceptions/validation.rb +25 -9
- data/lib/grape/exceptions/validation_array_errors.rb +5 -0
- data/lib/grape/exceptions/validation_errors.rb +22 -26
- data/lib/grape/formatter/base.rb +16 -0
- data/lib/grape/formatter/json.rb +4 -6
- data/lib/grape/formatter/serializable_hash.rb +6 -10
- data/lib/grape/formatter/txt.rb +3 -5
- data/lib/grape/formatter/xml.rb +4 -6
- data/lib/grape/formatter.rb +7 -25
- data/lib/grape/json.rb +46 -0
- data/lib/grape/locale/en.yml +43 -42
- data/lib/grape/middleware/auth/base.rb +11 -33
- data/lib/grape/middleware/auth/dsl.rb +37 -31
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/base.rb +56 -33
- data/lib/grape/middleware/deprecated_options_hash_access.rb +19 -0
- data/lib/grape/middleware/error.rb +183 -91
- data/lib/grape/middleware/formatter.rb +94 -105
- data/lib/grape/middleware/precomputed_content_types.rb +46 -0
- data/lib/grape/middleware/stack.rb +27 -38
- data/lib/grape/middleware/versioner/accept_version_header.rb +6 -33
- data/lib/grape/middleware/versioner/base.rb +72 -0
- data/lib/grape/middleware/versioner/header.rb +44 -129
- data/lib/grape/middleware/versioner/param.rb +4 -25
- data/lib/grape/middleware/versioner/path.rb +13 -32
- data/lib/grape/middleware/versioner.rb +7 -14
- data/lib/grape/mountable.rb +22 -0
- data/lib/grape/namespace.rb +18 -12
- data/lib/grape/params_builder/base.rb +20 -0
- data/lib/grape/params_builder/hash.rb +11 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
- data/lib/grape/params_builder/hashie_mash.rb +11 -0
- data/lib/grape/params_builder.rb +15 -0
- data/lib/grape/parser/base.rb +16 -0
- data/lib/grape/parser/json.rb +6 -8
- data/lib/grape/parser/xml.rb +6 -8
- data/lib/grape/parser.rb +5 -23
- data/lib/grape/path.rb +38 -63
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +168 -26
- data/lib/grape/router/base_route.rb +48 -0
- data/lib/grape/router/greedy_route.rb +26 -0
- data/lib/grape/router/mustermann_pattern.rb +44 -0
- data/lib/grape/router/pattern.rb +30 -34
- data/lib/grape/router/route.rb +28 -61
- data/lib/grape/router.rb +71 -86
- data/lib/grape/serve_stream/file_body.rb +1 -0
- data/lib/grape/serve_stream/sendfile_response.rb +3 -5
- data/lib/grape/serve_stream/stream_response.rb +1 -0
- data/lib/grape/testing.rb +33 -0
- data/lib/grape/util/api_description.rb +58 -0
- data/lib/grape/util/base_inheritable.rb +14 -14
- data/lib/grape/util/cache.rb +1 -3
- data/lib/grape/util/deep_freeze.rb +35 -0
- data/lib/grape/util/endpoint_configuration.rb +1 -1
- data/lib/grape/util/header.rb +13 -0
- data/lib/grape/util/inheritable_setting.rb +51 -27
- data/lib/grape/util/inheritable_values.rb +7 -5
- data/lib/grape/util/lazy/base.rb +16 -0
- data/lib/grape/util/lazy/block.rb +22 -0
- data/lib/grape/util/lazy/value.rb +31 -0
- data/lib/grape/util/lazy/value_array.rb +21 -0
- data/lib/grape/util/lazy/value_enumerable.rb +31 -0
- data/lib/grape/util/lazy/value_hash.rb +21 -0
- data/lib/grape/util/media_type.rb +67 -0
- data/lib/grape/util/path_normalizer.rb +34 -0
- data/lib/grape/util/registry.rb +27 -0
- data/lib/grape/util/reverse_stackable_values.rb +1 -6
- data/lib/grape/util/stackable_values.rb +12 -14
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +43 -27
- data/lib/grape/validations/coerce_options.rb +21 -0
- data/lib/grape/validations/contract_scope.rb +28 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/oneof_collector.rb +39 -0
- data/lib/grape/validations/param_scope_tracker.rb +62 -0
- data/lib/grape/validations/params_documentation.rb +52 -0
- data/lib/grape/validations/params_scope.rb +180 -303
- data/lib/grape/validations/shared_options.rb +19 -0
- data/lib/grape/validations/single_attribute_iterator.rb +2 -2
- data/lib/grape/validations/types/array_coercer.rb +4 -7
- data/lib/grape/validations/types/custom_type_coercer.rb +41 -85
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +1 -1
- data/lib/grape/validations/types/dry_type_coercer.rb +15 -28
- data/lib/grape/validations/types/json.rb +0 -2
- data/lib/grape/validations/types/primitive_coercer.rb +11 -35
- data/lib/grape/validations/types/set_coercer.rb +1 -4
- data/lib/grape/validations/types/variant_collection_coercer.rb +11 -0
- data/lib/grape/validations/types.rb +29 -54
- data/lib/grape/validations/validations_spec.rb +164 -0
- 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 +120 -36
- data/lib/grape/validations/validators/coerce_validator.rb +18 -36
- data/lib/grape/validations/validators/contract_scope_validator.rb +45 -0
- data/lib/grape/validations/validators/default_validator.rb +13 -16
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +15 -5
- data/lib/grape/validations/validators/length_validator.rb +48 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +12 -9
- data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
- data/lib/grape/validations/validators/oneof_validator.rb +49 -0
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +11 -3
- data/lib/grape/validations/validators/same_as_validator.rb +6 -15
- data/lib/grape/validations/validators/values_validator.rb +36 -65
- data/lib/grape/validations.rb +8 -21
- data/lib/grape/version.rb +1 -2
- data/lib/grape/xml.rb +17 -0
- data/lib/grape.rb +75 -288
- metadata +79 -291
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -19
- data/lib/grape/dsl/configuration.rb +0 -15
- data/lib/grape/eager_load.rb +0 -20
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/missing_option.rb +0 -11
- data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
- data/lib/grape/exceptions/unknown_options.rb +0 -11
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -27
- data/lib/grape/extensions/hash.rb +0 -22
- data/lib/grape/extensions/hashie/mash.rb +0 -26
- data/lib/grape/http/headers.rb +0 -61
- data/lib/grape/middleware/globals.rb +0 -16
- data/lib/grape/middleware/helpers.rb +0 -12
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
- data/lib/grape/router/attribute_translator.rb +0 -63
- data/lib/grape/types/invalid_value.rb +0 -8
- data/lib/grape/util/json.rb +0 -12
- data/lib/grape/util/lazy_block.rb +0 -27
- data/lib/grape/util/lazy_object.rb +0 -43
- data/lib/grape/util/lazy_value.rb +0 -91
- data/lib/grape/util/registrable.rb +0 -15
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/util/xml.rb +0 -10
- data/lib/grape/validations/attributes_doc.rb +0 -58
- data/lib/grape/validations/types/build_coercer.rb +0 -94
- data/lib/grape/validations/validator_factory.rb +0 -15
- data/spec/grape/api/custom_validations_spec.rb +0 -213
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -509
- data/spec/grape/api_spec.rb +0 -4356
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -98
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -531
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -225
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/grape_spec.rb +0 -9
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -126
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/base_spec.rb +0 -38
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -733
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2030
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/deprecated_class_examples.rb +0 -16
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'grape/exceptions/base'
|
|
4
|
-
|
|
5
3
|
module Grape
|
|
6
4
|
module Exceptions
|
|
7
|
-
class ValidationErrors <
|
|
8
|
-
ERRORS_FORMAT_KEY = 'grape.errors.format'
|
|
9
|
-
DEFAULT_ERRORS_FORMAT = '%{attributes} %{message}'
|
|
10
|
-
|
|
11
|
-
include Enumerable
|
|
12
|
-
|
|
5
|
+
class ValidationErrors < Base
|
|
13
6
|
attr_reader :errors
|
|
14
7
|
|
|
15
|
-
def initialize(
|
|
16
|
-
@errors = errors.group_by(&:params)
|
|
17
|
-
super
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def each
|
|
21
|
-
errors.each_pair do |attribute, errors|
|
|
22
|
-
errors.each do |error|
|
|
23
|
-
yield attribute, error
|
|
24
|
-
end
|
|
25
|
-
end
|
|
8
|
+
def initialize(exceptions: [], headers: {})
|
|
9
|
+
@errors = exceptions.flat_map(&:errors).group_by(&:params)
|
|
10
|
+
super(message: full_messages.join(', '), status: 400, headers:)
|
|
26
11
|
end
|
|
27
12
|
|
|
28
13
|
def as_json(**_opts)
|
|
@@ -39,17 +24,28 @@ module Grape
|
|
|
39
24
|
end
|
|
40
25
|
|
|
41
26
|
def full_messages
|
|
42
|
-
messages =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
messages = errors.flat_map do |attributes, errs|
|
|
28
|
+
errs.map do |error|
|
|
29
|
+
translate(
|
|
30
|
+
:format,
|
|
31
|
+
scope: 'grape.errors',
|
|
32
|
+
default: '%<attributes>s %<message>s',
|
|
33
|
+
attributes: translate_attributes(attributes),
|
|
34
|
+
message: error.message
|
|
35
|
+
)
|
|
36
|
+
end
|
|
49
37
|
end
|
|
50
38
|
messages.uniq!
|
|
51
39
|
messages
|
|
52
40
|
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def translate_attributes(keys)
|
|
45
|
+
keys.map do |key|
|
|
46
|
+
translate(key, scope: 'grape.errors.attributes', default: key.to_s)
|
|
47
|
+
end.join(', ')
|
|
48
|
+
end
|
|
53
49
|
end
|
|
54
50
|
end
|
|
55
51
|
end
|
data/lib/grape/formatter/json.rb
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Formatter
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return object.to_json if object.respond_to?(:to_json)
|
|
5
|
+
class Json < Base
|
|
6
|
+
def self.call(object, _env)
|
|
7
|
+
return object.to_json if object.respond_to?(:to_json)
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
end
|
|
9
|
+
::Grape::Json.dump(object)
|
|
12
10
|
end
|
|
13
11
|
end
|
|
14
12
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Formatter
|
|
5
|
-
|
|
5
|
+
class SerializableHash < Base
|
|
6
6
|
class << self
|
|
7
7
|
def call(object, _env)
|
|
8
8
|
return object if object.is_a?(String)
|
|
@@ -19,15 +19,11 @@ module Grape
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def serialize(object)
|
|
22
|
-
if object.respond_to?
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
object.transform_values { |v| serialize(v) }
|
|
28
|
-
else
|
|
29
|
-
object
|
|
30
|
-
end
|
|
22
|
+
return object.serializable_hash if object.respond_to?(:serializable_hash)
|
|
23
|
+
return object.map(&:serializable_hash) if array_serializable?(object)
|
|
24
|
+
return object.transform_values { |v| serialize(v) } if object.is_a?(Hash)
|
|
25
|
+
|
|
26
|
+
object
|
|
31
27
|
end
|
|
32
28
|
|
|
33
29
|
def array_serializable?(object)
|
data/lib/grape/formatter/txt.rb
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Formatter
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
object.respond_to?(:to_txt) ? object.to_txt : object.to_s
|
|
9
|
-
end
|
|
5
|
+
class Txt < Base
|
|
6
|
+
def self.call(object, _env)
|
|
7
|
+
object.respond_to?(:to_txt) ? object.to_txt : object.to_s
|
|
10
8
|
end
|
|
11
9
|
end
|
|
12
10
|
end
|
data/lib/grape/formatter/xml.rb
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Formatter
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return object.to_xml if object.respond_to?(:to_xml)
|
|
5
|
+
class Xml < Base
|
|
6
|
+
def self.call(object, _env)
|
|
7
|
+
return object.to_xml if object.respond_to?(:to_xml)
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
end
|
|
9
|
+
raise Grape::Exceptions::InvalidFormatter.new(object.class, 'xml')
|
|
12
10
|
end
|
|
13
11
|
end
|
|
14
12
|
end
|
data/lib/grape/formatter.rb
CHANGED
|
@@ -2,34 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module Grape
|
|
4
4
|
module Formatter
|
|
5
|
-
extend Util::
|
|
5
|
+
extend Grape::Util::Registry
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
def builtin_formatters
|
|
9
|
-
@builtin_formatters ||= {
|
|
10
|
-
json: Grape::Formatter::Json,
|
|
11
|
-
jsonapi: Grape::Formatter::Json,
|
|
12
|
-
serializable_hash: Grape::Formatter::SerializableHash,
|
|
13
|
-
txt: Grape::Formatter::Txt,
|
|
14
|
-
xml: Grape::Formatter::Xml
|
|
15
|
-
}
|
|
16
|
-
end
|
|
7
|
+
module_function
|
|
17
8
|
|
|
18
|
-
|
|
19
|
-
builtin_formatters.merge(default_elements).merge!(options[:formatters] || {})
|
|
20
|
-
end
|
|
9
|
+
DEFAULT_LAMBDA_FORMATTER = ->(obj, _env) { obj }
|
|
21
10
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
->(obj, _env) { obj }
|
|
27
|
-
when Symbol
|
|
28
|
-
method(spec)
|
|
29
|
-
else
|
|
30
|
-
spec
|
|
31
|
-
end
|
|
32
|
-
end
|
|
11
|
+
def formatter_for(api_format, formatters)
|
|
12
|
+
return formatters[api_format] if formatters&.key?(api_format)
|
|
13
|
+
|
|
14
|
+
registry[api_format] || DEFAULT_LAMBDA_FORMATTER
|
|
33
15
|
end
|
|
34
16
|
end
|
|
35
17
|
end
|
data/lib/grape/json.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
if defined?(::MultiJSON)
|
|
5
|
+
# Since multi_json 1.21.0, MultiJSON.dump is deprecated in favor of
|
|
6
|
+
# MultiJSON.generate (removed in 2.0). Keep Grape's dump surface but route
|
|
7
|
+
# it to the non-deprecated name — identical output, no deprecation warning.
|
|
8
|
+
# https://github.com/sferik/multi_json/blob/v1.21.1/CHANGELOG.md#deprecated
|
|
9
|
+
module Json
|
|
10
|
+
ParseError = ::MultiJSON::ParseError
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def dump(object)
|
|
14
|
+
::MultiJSON.generate(object)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# parse is not deprecated; it's re-exposed (not renamed) because this
|
|
18
|
+
# facade is its own module and no longer inherits MultiJSON's methods.
|
|
19
|
+
def parse(source)
|
|
20
|
+
::MultiJSON.parse(source)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
elsif defined?(::MultiJson)
|
|
25
|
+
# Legacy multi_json (< 1.21) predates generate/parse and only exposes
|
|
26
|
+
# dump/load. Map Grape's surface onto them so the call sites stay
|
|
27
|
+
# engine-agnostic (these names are not deprecated on < 1.21).
|
|
28
|
+
module Json
|
|
29
|
+
# Mutually exclusive with the MultiJSON branch above; only one runs.
|
|
30
|
+
ParseError = ::MultiJson::ParseError # rubocop:disable Lint/ConstantReassignment
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
def dump(object)
|
|
34
|
+
::MultiJson.dump(object)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def parse(source)
|
|
38
|
+
::MultiJson.load(source)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
else
|
|
43
|
+
Json = ::JSON
|
|
44
|
+
Json::ParseError = Json::ParserError
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/grape/locale/en.yml
CHANGED
|
@@ -1,55 +1,56 @@
|
|
|
1
|
+
---
|
|
1
2
|
en:
|
|
2
3
|
grape:
|
|
3
4
|
errors:
|
|
4
|
-
format:
|
|
5
|
+
format: '%{attributes} %{message}'
|
|
5
6
|
messages:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
regexp: 'is invalid'
|
|
7
|
+
all_or_none: 'provide all or none of parameters'
|
|
8
|
+
at_least_one: 'are missing, at least one parameter must be provided'
|
|
9
9
|
blank: 'is empty'
|
|
10
|
-
|
|
10
|
+
coerce: 'is invalid'
|
|
11
|
+
exactly_one: 'are missing, exactly one parameter must be provided'
|
|
11
12
|
except_values: 'has a value not allowed'
|
|
12
|
-
same_as: 'is not the same as %{parameter}'
|
|
13
|
-
missing_vendor_option:
|
|
14
|
-
problem: 'missing :vendor option'
|
|
15
|
-
summary: 'when version using header, you must specify :vendor option'
|
|
16
|
-
resolution: "eg: version 'v1', using: :header, vendor: 'twitter'"
|
|
17
|
-
missing_mime_type:
|
|
18
|
-
problem: 'missing mime type for %{new_format}'
|
|
19
|
-
resolution:
|
|
20
|
-
"you can choose existing mime type from Grape::ContentTypes::CONTENT_TYPES
|
|
21
|
-
or add your own with content_type :%{new_format}, 'application/%{new_format}'
|
|
22
|
-
"
|
|
23
|
-
invalid_with_option_for_represent:
|
|
24
|
-
problem: 'you must specify an entity class in the :with option'
|
|
25
|
-
resolution: 'eg: represent User, :with => Entity::User'
|
|
26
|
-
missing_option: 'you must specify :%{option} options'
|
|
27
|
-
invalid_formatter: 'cannot convert %{klass} to %{to_format}'
|
|
28
|
-
invalid_versioner_option:
|
|
29
|
-
problem: 'unknown :using for versioner: %{strategy}'
|
|
30
|
-
resolution: 'available strategy for :using is :path, :header, :accept_version_header, :param'
|
|
31
|
-
unknown_validator: 'unknown validator: %{validator_type}'
|
|
32
|
-
unknown_options: 'unknown options: %{options}'
|
|
33
|
-
unknown_parameter: 'unknown parameter: %{param}'
|
|
34
13
|
incompatible_option_values: '%{option1}: %{value1} is incompatible with %{option2}: %{value2}'
|
|
35
|
-
|
|
36
|
-
at_least_one: 'are missing, at least one parameter must be provided'
|
|
37
|
-
exactly_one: 'are missing, exactly one parameter must be provided'
|
|
38
|
-
all_or_none: 'provide all or none of parameters'
|
|
39
|
-
missing_group_type: 'group type is required'
|
|
40
|
-
unsupported_group_type: 'group type must be Array, Hash, JSON or Array[JSON]'
|
|
41
|
-
invalid_message_body:
|
|
42
|
-
problem: "message body does not match declared format"
|
|
43
|
-
resolution:
|
|
44
|
-
"when specifying %{body_format} as content-type, you must pass valid
|
|
45
|
-
%{body_format} in the request's 'body'
|
|
46
|
-
"
|
|
47
|
-
empty_message_body: 'empty message body supplied with %{body_format} content-type'
|
|
48
|
-
too_many_multipart_files: "the number of uploaded files exceeded the system's configured limit (%{limit})"
|
|
14
|
+
internal_server_error: 'Internal Server Error'
|
|
49
15
|
invalid_accept_header:
|
|
50
16
|
problem: 'invalid accept header'
|
|
51
17
|
resolution: '%{message}'
|
|
18
|
+
invalid_formatter: 'cannot convert %{klass} to %{to_format}'
|
|
19
|
+
invalid_message_body:
|
|
20
|
+
problem: 'message body does not match declared format'
|
|
21
|
+
resolution: 'when specifying %{body_format} as content-type, you must pass valid %{body_format} in the request''s ''body'' '
|
|
22
|
+
invalid_response: 'Invalid response'
|
|
52
23
|
invalid_version_header:
|
|
53
24
|
problem: 'invalid version header'
|
|
54
25
|
resolution: '%{message}'
|
|
55
|
-
|
|
26
|
+
invalid_versioner_option:
|
|
27
|
+
problem: 'unknown :using for versioner: %{strategy}'
|
|
28
|
+
resolution: 'available strategy for :using is :path, :header, :accept_version_header, :param'
|
|
29
|
+
invalid_with_option_for_represent:
|
|
30
|
+
problem: 'you must specify an entity class in the :with option'
|
|
31
|
+
resolution: 'eg: represent User, :with => Entity::User'
|
|
32
|
+
length: 'is expected to have length within %{min} and %{max}'
|
|
33
|
+
length_is: 'is expected to have length exactly equal to %{is}'
|
|
34
|
+
length_max: 'is expected to have length less than or equal to %{max}'
|
|
35
|
+
length_min: 'is expected to have length greater than or equal to %{min}'
|
|
36
|
+
missing_group_type: 'group type is required'
|
|
37
|
+
missing_mime_type:
|
|
38
|
+
problem: 'missing mime type for %{new_format}'
|
|
39
|
+
resolution: 'you can choose existing mime type from Grape::ContentTypes::CONTENT_TYPES or add your own with content_type :%{new_format}, ''application/%{new_format}'' '
|
|
40
|
+
missing_option: 'you must specify :%{option} options'
|
|
41
|
+
missing_vendor_option:
|
|
42
|
+
problem: 'missing :vendor option'
|
|
43
|
+
resolution: 'eg: version ''v1'', using: :header, vendor: ''twitter'''
|
|
44
|
+
summary: 'when version using header, you must specify :vendor option'
|
|
45
|
+
mutual_exclusion: 'are mutually exclusive'
|
|
46
|
+
oneof: 'does not match any of the allowed schemas'
|
|
47
|
+
presence: 'is missing'
|
|
48
|
+
regexp: 'is invalid'
|
|
49
|
+
same_as: 'is not the same as %{parameter}'
|
|
50
|
+
unknown_auth_strategy: 'unknown auth strategy: %{strategy}'
|
|
51
|
+
unknown_options: 'unknown options: %{options}'
|
|
52
|
+
unknown_parameter: 'unknown parameter: %{param}'
|
|
53
|
+
unknown_params_builder: 'unknown params_builder: %{params_builder_type}'
|
|
54
|
+
unknown_validator: 'unknown validator: %{validator_type}'
|
|
55
|
+
unsupported_group_type: 'group type must be Array, Hash, JSON or Array[JSON]'
|
|
56
|
+
values: 'does not have a valid value'
|
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'rack/auth/basic'
|
|
4
|
-
|
|
5
3
|
module Grape
|
|
6
4
|
module Middleware
|
|
7
5
|
module Auth
|
|
8
|
-
class Base
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
class Base < Grape::Middleware::Base
|
|
7
|
+
def initialize(app, **options)
|
|
8
|
+
super
|
|
9
|
+
return unless options.key?(:type)
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@options = options.shift
|
|
11
|
+
@auth_strategy = Grape::Middleware::Auth::Strategies[options[:type]]
|
|
12
|
+
raise Grape::Exceptions::UnknownAuthStrategy.new(strategy: options[:type]) unless @auth_strategy
|
|
16
13
|
end
|
|
17
14
|
|
|
18
|
-
def call(env)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
self.env = env
|
|
24
|
-
|
|
25
|
-
if options.key?(:type)
|
|
26
|
-
auth_proc = options[:proc]
|
|
27
|
-
auth_proc_context = context
|
|
28
|
-
|
|
29
|
-
strategy_info = Grape::Middleware::Auth::Strategies[options[:type]]
|
|
30
|
-
|
|
31
|
-
throw(:error, status: 401, message: 'API Authorization Failed.') if strategy_info.blank?
|
|
32
|
-
|
|
33
|
-
strategy = strategy_info.create(@app, options) do |*args|
|
|
34
|
-
auth_proc_context.instance_exec(*args, &auth_proc)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
strategy.call(env)
|
|
38
|
-
|
|
39
|
-
else
|
|
40
|
-
app.call(env)
|
|
41
|
-
end
|
|
15
|
+
def call!(env)
|
|
16
|
+
@env = env
|
|
17
|
+
@auth_strategy.create(app, options) do |*args|
|
|
18
|
+
context.instance_exec(*args, &options[:proc])
|
|
19
|
+
end.call(env)
|
|
42
20
|
end
|
|
43
21
|
end
|
|
44
22
|
end
|
|
@@ -1,45 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'rack/auth/basic'
|
|
4
|
-
|
|
5
3
|
module Grape
|
|
6
4
|
module Middleware
|
|
7
5
|
module Auth
|
|
8
6
|
module DSL
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# Add an authentication type to the API. Currently
|
|
13
|
-
# only `:http_basic`, `:http_digest` are supported.
|
|
14
|
-
def auth(type = nil, options = {}, &block)
|
|
15
|
-
if type
|
|
16
|
-
namespace_inheritable(:auth, options.reverse_merge(type: type.to_sym, proc: block))
|
|
17
|
-
use Grape::Middleware::Auth::Base, namespace_inheritable(:auth)
|
|
18
|
-
else
|
|
19
|
-
namespace_inheritable(:auth)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
7
|
+
def auth(type = nil, *legacy_options, **options, &block)
|
|
8
|
+
namespace_inheritable = inheritable_setting.namespace_inheritable
|
|
9
|
+
return namespace_inheritable[:auth] unless type
|
|
22
10
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def http_basic(options = {}, &block)
|
|
28
|
-
options[:realm] ||= 'API Authorization'
|
|
29
|
-
auth :http_basic, options, &block
|
|
30
|
-
end
|
|
11
|
+
options = merge_legacy_auth_options(:auth, legacy_options, options)
|
|
12
|
+
namespace_inheritable[:auth] = { type: type.to_sym, proc: block }.merge!(options)
|
|
13
|
+
use Grape::Middleware::Auth::Base, namespace_inheritable[:auth]
|
|
14
|
+
end
|
|
31
15
|
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
# Add HTTP Basic authorization to the API.
|
|
17
|
+
#
|
|
18
|
+
# @param options [Hash] a hash of options
|
|
19
|
+
# @option options [String] :realm "API Authorization" the HTTP Basic realm
|
|
20
|
+
def http_basic(*legacy_options, **options, &)
|
|
21
|
+
options = merge_legacy_auth_options(:http_basic, legacy_options, options)
|
|
22
|
+
options[:realm] ||= 'API Authorization'
|
|
23
|
+
auth(:http_basic, **options, &)
|
|
24
|
+
end
|
|
34
25
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
options[:opaque] ||= 'secret'
|
|
39
|
-
end
|
|
26
|
+
def http_digest(*legacy_options, **options, &)
|
|
27
|
+
options = merge_legacy_auth_options(:http_digest, legacy_options, options)
|
|
28
|
+
options[:realm] ||= 'API Authorization'
|
|
40
29
|
|
|
41
|
-
|
|
30
|
+
if options[:realm].respond_to?(:values_at)
|
|
31
|
+
options[:realm][:opaque] ||= 'secret'
|
|
32
|
+
else
|
|
33
|
+
options[:opaque] ||= 'secret'
|
|
42
34
|
end
|
|
35
|
+
|
|
36
|
+
auth(:http_digest, **options, &)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# @deprecated Passing a positional options Hash is deprecated; pass
|
|
42
|
+
# keyword arguments instead. Kept so downstream callers keep working
|
|
43
|
+
# through the deprecation cycle.
|
|
44
|
+
def merge_legacy_auth_options(method_name, legacy_options, options)
|
|
45
|
+
return options if legacy_options.empty?
|
|
46
|
+
|
|
47
|
+
Grape.deprecator.warn("Passing a positional options Hash to `#{method_name}` is deprecated. Pass keyword arguments instead.")
|
|
48
|
+
legacy_options.first.merge(options)
|
|
43
49
|
end
|
|
44
50
|
end
|
|
45
51
|
end
|
|
@@ -12,8 +12,7 @@ module Grape
|
|
|
12
12
|
|
|
13
13
|
def auth_strategies
|
|
14
14
|
@auth_strategies ||= {
|
|
15
|
-
http_basic: StrategyInfo.new(Rack::Auth::Basic, ->(settings) { [settings[:realm]] })
|
|
16
|
-
http_digest: StrategyInfo.new(Rack::Auth::Digest::MD5, ->(settings) { [settings[:realm], settings[:opaque]] })
|
|
15
|
+
http_basic: StrategyInfo.new(Rack::Auth::Basic, ->(settings) { [settings[:realm]] })
|
|
17
16
|
}
|
|
18
17
|
end
|
|
19
18
|
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'grape/dsl/headers'
|
|
4
|
-
|
|
5
3
|
module Grape
|
|
6
4
|
module Middleware
|
|
7
5
|
class Base
|
|
8
|
-
include Helpers
|
|
9
|
-
|
|
10
|
-
attr_reader :app, :env, :options
|
|
11
|
-
|
|
12
|
-
TEXT_HTML = 'text/html'
|
|
13
|
-
|
|
14
6
|
include Grape::DSL::Headers
|
|
15
7
|
|
|
8
|
+
attr_reader :app, :env, :options, :config
|
|
9
|
+
|
|
16
10
|
# @param [Rack Application] app The standard argument for a Rack middleware.
|
|
17
|
-
# @param [Hash] options
|
|
18
|
-
|
|
11
|
+
# @param [Hash] options Options forwarded to the subclass. When the
|
|
12
|
+
# subclass declares an `Options` Data class, the kwargs are routed
|
|
13
|
+
# through it and exposed via {#config}; {#options} keeps returning a
|
|
14
|
+
# frozen Hash representation for back-compat with subclasses that read
|
|
15
|
+
# `options[:key]`. Otherwise the kwargs are deep-merged with the
|
|
16
|
+
# subclass's `DEFAULT_OPTIONS` Hash (legacy path) and frozen.
|
|
17
|
+
def initialize(app, **options)
|
|
19
18
|
@app = app
|
|
20
|
-
|
|
19
|
+
if (config_class = options_data_class)
|
|
20
|
+
@config = config_class.new(**options)
|
|
21
|
+
@options = @config.to_h.freeze
|
|
22
|
+
else
|
|
23
|
+
@options = merge_default_options(options).freeze
|
|
24
|
+
end
|
|
21
25
|
@app_response = nil
|
|
22
26
|
end
|
|
23
27
|
|
|
24
|
-
def default_options
|
|
25
|
-
{}
|
|
26
|
-
end
|
|
27
|
-
|
|
28
28
|
def call(env)
|
|
29
29
|
dup.call!(env).to_a
|
|
30
30
|
end
|
|
@@ -57,40 +57,63 @@ module Grape
|
|
|
57
57
|
# @return [Response, nil] a Rack SPEC response or nil to call the application afterwards.
|
|
58
58
|
def after; end
|
|
59
59
|
|
|
60
|
-
def
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@app_response = Rack::Response.new(@app_response[2], @app_response[0], @app_response[1])
|
|
60
|
+
def rack_request
|
|
61
|
+
@rack_request ||= Rack::Request.new(env)
|
|
64
62
|
end
|
|
65
63
|
|
|
66
|
-
def
|
|
67
|
-
|
|
64
|
+
def context
|
|
65
|
+
env[Grape::Env::API_ENDPOINT]
|
|
68
66
|
end
|
|
69
67
|
|
|
70
|
-
def
|
|
71
|
-
|
|
72
|
-
end
|
|
68
|
+
def response
|
|
69
|
+
return @app_response if @app_response.is_a?(Rack::Response)
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
content_type_for(env[Grape::Env::API_FORMAT] || options[:format]) || TEXT_HTML
|
|
71
|
+
@app_response = Rack::Response[*@app_response]
|
|
76
72
|
end
|
|
77
73
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
def query_params
|
|
75
|
+
rack_request.GET
|
|
76
|
+
rescue *Grape::RACK_ERRORS
|
|
77
|
+
raise Grape::Exceptions::RequestError
|
|
82
78
|
end
|
|
83
79
|
|
|
84
80
|
private
|
|
85
81
|
|
|
86
82
|
def merge_headers(response)
|
|
87
|
-
return
|
|
83
|
+
return if @header.blank?
|
|
88
84
|
|
|
89
85
|
case response
|
|
90
|
-
when Rack::Response then response.headers.merge!(
|
|
91
|
-
when Array then response[1].merge!(
|
|
86
|
+
when Rack::Response then response.headers.merge!(@header)
|
|
87
|
+
when Array then response[1].merge!(@header)
|
|
92
88
|
end
|
|
93
89
|
end
|
|
90
|
+
|
|
91
|
+
def merge_default_options(options)
|
|
92
|
+
return default_options.deep_merge(options) if respond_to?(:default_options)
|
|
93
|
+
|
|
94
|
+
default_options_constant&.deep_merge(options) || options
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# self.class::Options honours middleware inheritance (e.g. Versioner::Path
|
|
98
|
+
# → Versioner::Base) and, unlike const_defined?, never resolves a
|
|
99
|
+
# top-level ::Options on Object. Absent an own/inherited Options class,
|
|
100
|
+
# the lookup raises NameError and we fall back to the legacy path.
|
|
101
|
+
def options_data_class
|
|
102
|
+
self.class::Options
|
|
103
|
+
rescue NameError
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Same idea as {#options_data_class} for the legacy DEFAULT_OPTIONS Hash.
|
|
108
|
+
def default_options_constant
|
|
109
|
+
self.class::DEFAULT_OPTIONS
|
|
110
|
+
rescue NameError
|
|
111
|
+
nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def try_scrub(obj)
|
|
115
|
+
obj.respond_to?(:valid_encoding?) && !obj.valid_encoding? ? obj.scrub : obj
|
|
116
|
+
end
|
|
94
117
|
end
|
|
95
118
|
end
|
|
96
119
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module Middleware
|
|
5
|
+
# Mixin for per-middleware +Options+ +Data+ classes that need to keep
|
|
6
|
+
# accepting legacy +data[:key]+ Hash-style access while nudging callers
|
|
7
|
+
# toward the named accessor. Emits a +Grape.deprecator+ warning then
|
|
8
|
+
# forwards to +public_send(key)+.
|
|
9
|
+
module DeprecatedOptionsHashAccess
|
|
10
|
+
def [](key)
|
|
11
|
+
Grape.deprecator.warn(
|
|
12
|
+
"`#{self.class.name}#[]` is deprecated. " \
|
|
13
|
+
"Use the named accessor `#{key}` instead."
|
|
14
|
+
)
|
|
15
|
+
public_send(key) if members.include?(key)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|