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
data/lib/grape/dsl/routing.rb
CHANGED
|
@@ -3,228 +3,303 @@
|
|
|
3
3
|
module Grape
|
|
4
4
|
module DSL
|
|
5
5
|
module Routing
|
|
6
|
-
|
|
7
|
-
include Grape::DSL::Configuration
|
|
8
|
-
|
|
9
|
-
module ClassMethods
|
|
10
|
-
attr_reader :endpoints
|
|
11
|
-
|
|
12
|
-
# Specify an API version.
|
|
13
|
-
#
|
|
14
|
-
# @example API with legacy support.
|
|
15
|
-
# class MyAPI < Grape::API
|
|
16
|
-
# version 'v2'
|
|
17
|
-
#
|
|
18
|
-
# get '/main' do
|
|
19
|
-
# {some: 'data'}
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# version 'v1' do
|
|
23
|
-
# get '/main' do
|
|
24
|
-
# {legacy: 'data'}
|
|
25
|
-
# end
|
|
26
|
-
# end
|
|
27
|
-
# end
|
|
28
|
-
#
|
|
29
|
-
def version(*args, &block)
|
|
30
|
-
if args.any?
|
|
31
|
-
options = args.extract_options!
|
|
32
|
-
options = options.reverse_merge(using: :path)
|
|
33
|
-
requested_versions = args.flatten
|
|
34
|
-
|
|
35
|
-
raise Grape::Exceptions::MissingVendorOption.new if options[:using] == :header && !options.key?(:vendor)
|
|
36
|
-
|
|
37
|
-
@versions = versions | requested_versions
|
|
38
|
-
|
|
39
|
-
if block
|
|
40
|
-
within_namespace do
|
|
41
|
-
namespace_inheritable(:version, requested_versions)
|
|
42
|
-
namespace_inheritable(:version_options, options)
|
|
43
|
-
|
|
44
|
-
instance_eval(&block)
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
namespace_inheritable(:version, requested_versions)
|
|
48
|
-
namespace_inheritable(:version_options, options)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
6
|
+
attr_reader :endpoints
|
|
51
7
|
|
|
52
|
-
|
|
53
|
-
|
|
8
|
+
def given(conditional_option, &)
|
|
9
|
+
return unless conditional_option
|
|
54
10
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
11
|
+
mounted(&)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def mounted(&block)
|
|
15
|
+
evaluate_as_instance_with_configuration(block, lazy: true)
|
|
16
|
+
end
|
|
59
17
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
18
|
+
def cascade(value = nil)
|
|
19
|
+
return inheritable_setting.namespace_inheritable.key?(:cascade) ? !inheritable_setting.namespace_inheritable[:cascade].nil? : true if value.nil?
|
|
20
|
+
|
|
21
|
+
inheritable_setting.namespace_inheritable[:cascade] = value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Specify an API version.
|
|
25
|
+
#
|
|
26
|
+
# Called without arguments, returns the most recently declared version
|
|
27
|
+
# (or +nil+). Called with one or more version strings, registers them
|
|
28
|
+
# and stores a {Grape::DSL::VersionOptions} value object on the
|
|
29
|
+
# inheritable settings; when given a block, the registration applies
|
|
30
|
+
# within a nested namespace.
|
|
31
|
+
#
|
|
32
|
+
# @example API with legacy support.
|
|
33
|
+
# class MyAPI < Grape::API
|
|
34
|
+
# version 'v2'
|
|
35
|
+
#
|
|
36
|
+
# get '/main' do
|
|
37
|
+
# {some: 'data'}
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# version 'v1' do
|
|
41
|
+
# get '/main' do
|
|
42
|
+
# {legacy: 'data'}
|
|
43
|
+
# end
|
|
44
|
+
# end
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# @param args [Array<String, Symbol>] one or more version identifiers.
|
|
48
|
+
# @param using [Symbol] versioning strategy — one of +:path+ (default),
|
|
49
|
+
# +:header+, +:param+, or +:accept_version_header+.
|
|
50
|
+
# @param cascade [Boolean] forward to subsequent routes via the
|
|
51
|
+
# +X-Cascade+ header on version mismatch. Defaults to +true+.
|
|
52
|
+
# @param parameter [String] name of the query/body parameter that
|
|
53
|
+
# carries the version when +using: :param+. Defaults to +'apiver'+.
|
|
54
|
+
# @param strict [Boolean] reject requests that don't supply a usable
|
|
55
|
+
# version (header strategies). Defaults to +false+.
|
|
56
|
+
# @param vendor [String, nil] vendor segment for the +:header+
|
|
57
|
+
# strategy (+application/vnd.<vendor>-<version>+); required when
|
|
58
|
+
# +using: :header+.
|
|
59
|
+
# @yield optional block to scope routes under this version.
|
|
60
|
+
# @return [String, nil] the most recently declared version.
|
|
61
|
+
# @raise [Grape::Exceptions::MissingVendorOption] when +using: :header+
|
|
62
|
+
# is supplied without a +:vendor+.
|
|
63
|
+
def version(*args, using: :path, cascade: true, parameter: 'apiver', strict: false, vendor: nil, &block)
|
|
64
|
+
return @versions&.last if args.empty?
|
|
65
|
+
|
|
66
|
+
raise Grape::Exceptions::MissingVendorOption.new if using == :header && vendor.nil?
|
|
67
|
+
|
|
68
|
+
requested_versions = args.flatten.map(&:to_s)
|
|
69
|
+
options = VersionOptions.new(using:, cascade:, parameter:, strict:, vendor:)
|
|
70
|
+
|
|
71
|
+
@versions = versions | requested_versions
|
|
72
|
+
|
|
73
|
+
if block
|
|
65
74
|
within_namespace do
|
|
66
|
-
|
|
75
|
+
inheritable_setting.namespace_inheritable[:version] = requested_versions
|
|
76
|
+
inheritable_setting.namespace_inheritable[:version_options] = options
|
|
77
|
+
instance_eval(&block)
|
|
67
78
|
end
|
|
79
|
+
else
|
|
80
|
+
inheritable_setting.namespace_inheritable[:version] = requested_versions
|
|
81
|
+
inheritable_setting.namespace_inheritable[:version_options] = options
|
|
68
82
|
end
|
|
69
83
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
namespace_inheritable(:do_not_route_head, true)
|
|
73
|
-
end
|
|
84
|
+
@versions&.last
|
|
85
|
+
end
|
|
74
86
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end
|
|
87
|
+
# Define a root URL prefix for your entire API.
|
|
88
|
+
def prefix(prefix = nil)
|
|
89
|
+
return inheritable_setting.namespace_inheritable[:root_prefix] if prefix.nil?
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
inheritable_setting.namespace_inheritable[:root_prefix] = prefix.to_s
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Create a scope without affecting the URL.
|
|
95
|
+
#
|
|
96
|
+
# @param _name [Symbol] Purely placebo, just allows to name the scope to
|
|
97
|
+
# make the code more readable.
|
|
98
|
+
def scope(_name = nil, &block)
|
|
99
|
+
within_namespace do
|
|
100
|
+
nest(block)
|
|
82
101
|
end
|
|
102
|
+
end
|
|
83
103
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if app.respond_to?(:mount_instance)
|
|
88
|
-
opts_with = opts.any? ? opts.shift[:with] : {}
|
|
89
|
-
mount({ app.mount_instance(configuration: opts_with) => path })
|
|
90
|
-
next
|
|
91
|
-
end
|
|
92
|
-
in_setting = inheritable_setting
|
|
104
|
+
def build_with(build_with)
|
|
105
|
+
inheritable_setting.namespace_inheritable[:build_params_with] = build_with
|
|
106
|
+
end
|
|
93
107
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
108
|
+
# Do not route HEAD requests to GET requests automatically.
|
|
109
|
+
def do_not_route_head!
|
|
110
|
+
inheritable_setting.namespace_inheritable[:do_not_route_head] = true
|
|
111
|
+
end
|
|
97
112
|
|
|
98
|
-
|
|
113
|
+
# Do not automatically route OPTIONS.
|
|
114
|
+
def do_not_route_options!
|
|
115
|
+
inheritable_setting.namespace_inheritable[:do_not_route_options] = true
|
|
116
|
+
end
|
|
99
117
|
|
|
100
|
-
|
|
118
|
+
def lint!
|
|
119
|
+
inheritable_setting.namespace_inheritable[:lint] = true
|
|
120
|
+
end
|
|
101
121
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
122
|
+
def do_not_document!
|
|
123
|
+
inheritable_setting.namespace_inheritable[:do_not_document] = true
|
|
124
|
+
end
|
|
105
125
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
for: self
|
|
114
|
-
)
|
|
126
|
+
def mount(mounts, *opts)
|
|
127
|
+
mounts = { mounts => '/' } unless mounts.respond_to?(:each_pair)
|
|
128
|
+
mounts.each_pair do |app, path|
|
|
129
|
+
if app.respond_to?(:mount_instance)
|
|
130
|
+
opts_with = opts.any? ? opts.first[:with] : {}
|
|
131
|
+
mount({ app.mount_instance(configuration: opts_with) => path }, *opts)
|
|
132
|
+
next
|
|
115
133
|
end
|
|
116
|
-
|
|
134
|
+
in_setting = inheritable_setting
|
|
117
135
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
# class MyAPI < Grape::API
|
|
126
|
-
# route(:any, '/hello') do
|
|
127
|
-
# {hello: 'world'}
|
|
128
|
-
# end
|
|
129
|
-
# end
|
|
130
|
-
def route(methods, paths = ['/'], route_options = {}, &block)
|
|
131
|
-
methods = '*' if methods == :any
|
|
132
|
-
endpoint_options = {
|
|
133
|
-
method: methods,
|
|
134
|
-
path: paths,
|
|
135
|
-
for: self,
|
|
136
|
-
route_options: {
|
|
137
|
-
params: namespace_stackable_with_hash(:params) || {}
|
|
138
|
-
}.deep_merge(route_setting(:description) || {}).deep_merge(route_options || {})
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
new_endpoint = Grape::Endpoint.new(inheritable_setting, endpoint_options, &block)
|
|
142
|
-
endpoints << new_endpoint unless endpoints.any? { |e| e.equals?(new_endpoint) }
|
|
143
|
-
|
|
144
|
-
route_end
|
|
145
|
-
reset_validations!
|
|
146
|
-
end
|
|
136
|
+
# Past the mount_instance branch above, a Grape app here is an already
|
|
137
|
+
# instantiated Grape::API::Instance (vs. a bare Rack app).
|
|
138
|
+
if app.is_a?(Grape::Mountable)
|
|
139
|
+
mount_path = Grape::Util::PathNormalizer.call(path)
|
|
140
|
+
app.top_level_setting.namespace_stackable[:mount_path] = mount_path
|
|
141
|
+
|
|
142
|
+
app.inherit_settings(inheritable_setting)
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
route(supported_method, paths, options, &block)
|
|
144
|
+
in_setting = app.top_level_setting
|
|
145
|
+
|
|
146
|
+
app.change!
|
|
147
|
+
change!
|
|
153
148
|
end
|
|
154
|
-
end
|
|
155
149
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
#
|
|
163
|
-
# namespace :foo do
|
|
164
|
-
# get 'bar' do
|
|
165
|
-
# # defines the endpoint: GET /foo/bar
|
|
166
|
-
# end
|
|
167
|
-
# end
|
|
168
|
-
def namespace(space = nil, options = {}, &block)
|
|
169
|
-
@namespace_description = nil unless instance_variable_defined?(:@namespace_description) && @namespace_description
|
|
170
|
-
|
|
171
|
-
if space || block
|
|
172
|
-
within_namespace do
|
|
173
|
-
previous_namespace_description = @namespace_description
|
|
174
|
-
@namespace_description = (@namespace_description || {}).deep_merge(namespace_setting(:description) || {})
|
|
175
|
-
nest(block) do
|
|
176
|
-
namespace_stackable(:namespace, Namespace.new(space, **options)) if space
|
|
177
|
-
end
|
|
178
|
-
@namespace_description = previous_namespace_description
|
|
150
|
+
# When trying to mount multiple times the same endpoint, remove the previous ones
|
|
151
|
+
# from the list of endpoints if refresh_already_mounted parameter is true
|
|
152
|
+
refresh_already_mounted = opts.any? ? opts.first[:refresh_already_mounted] : false
|
|
153
|
+
if refresh_already_mounted && !endpoints.empty?
|
|
154
|
+
endpoints.delete_if do |endpoint|
|
|
155
|
+
endpoint.options[:app].to_s == app.to_s
|
|
179
156
|
end
|
|
180
|
-
else
|
|
181
|
-
Namespace.joined_space_path(namespace_stackable(:namespace))
|
|
182
157
|
end
|
|
158
|
+
|
|
159
|
+
endpoints << Grape::Endpoint.new(
|
|
160
|
+
in_setting,
|
|
161
|
+
method: :any,
|
|
162
|
+
path:,
|
|
163
|
+
app:,
|
|
164
|
+
route_options: { anchor: false },
|
|
165
|
+
forward_match: !app.respond_to?(:inheritable_setting),
|
|
166
|
+
for: self
|
|
167
|
+
)
|
|
183
168
|
end
|
|
169
|
+
end
|
|
184
170
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
171
|
+
# Defines a route that will be recognized
|
|
172
|
+
# by the Grape API.
|
|
173
|
+
#
|
|
174
|
+
# @param methods [HTTP Verb] One or more HTTP verbs that are accepted by this route. Set to `:any` if you want any verb to be accepted.
|
|
175
|
+
# @param paths [String] One or more strings representing the URL segment(s) for this route.
|
|
176
|
+
#
|
|
177
|
+
# @example Defining a basic route.
|
|
178
|
+
# class MyAPI < Grape::API
|
|
179
|
+
# route(:any, '/hello') do
|
|
180
|
+
# {hello: 'world'}
|
|
181
|
+
# end
|
|
182
|
+
# end
|
|
183
|
+
def route(methods, paths = ['/'], route_options = {}, &)
|
|
184
|
+
method = methods == :any ? '*' : methods
|
|
185
|
+
endpoint_params = inheritable_setting.namespace_stackable_with_hash(:params) || {}
|
|
186
|
+
endpoint_description = inheritable_setting.route[:description]
|
|
187
|
+
all_route_options = { params: endpoint_params }
|
|
188
|
+
all_route_options.deep_merge!(endpoint_description) if endpoint_description
|
|
189
|
+
all_route_options.deep_merge!(route_options) if route_options.present?
|
|
190
|
+
|
|
191
|
+
new_endpoint = Grape::Endpoint.new(
|
|
192
|
+
inheritable_setting,
|
|
193
|
+
method:,
|
|
194
|
+
path: paths,
|
|
195
|
+
for: self,
|
|
196
|
+
route_options: all_route_options,
|
|
197
|
+
&
|
|
198
|
+
)
|
|
199
|
+
endpoints << new_endpoint unless endpoints.include?(new_endpoint)
|
|
200
|
+
|
|
201
|
+
inheritable_setting.route_end
|
|
202
|
+
reset_validations!
|
|
203
|
+
end
|
|
189
204
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
205
|
+
Grape::HTTP_SUPPORTED_METHODS.each do |supported_method|
|
|
206
|
+
define_method supported_method.downcase do |path = '/', **options, &block|
|
|
207
|
+
route(supported_method, path, options, &block)
|
|
193
208
|
end
|
|
209
|
+
end
|
|
194
210
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
211
|
+
# Declare a "namespace", which prefixes all subordinate routes with its
|
|
212
|
+
# name. Any endpoints within a namespace, group, resource or segment,
|
|
213
|
+
# etc., will share their parent context as well as any configuration
|
|
214
|
+
# done in the namespace context.
|
|
215
|
+
#
|
|
216
|
+
# @example
|
|
217
|
+
#
|
|
218
|
+
# namespace :foo do
|
|
219
|
+
# get 'bar' do
|
|
220
|
+
# # defines the endpoint: GET /foo/bar
|
|
221
|
+
# end
|
|
222
|
+
# end
|
|
223
|
+
def namespace(space = nil, requirements: nil, **options, &block)
|
|
224
|
+
return Namespace.joined_space_path(inheritable_setting.namespace_stackable[:namespace]) unless space || block
|
|
225
|
+
|
|
226
|
+
within_namespace do
|
|
227
|
+
nest(block) do
|
|
228
|
+
inheritable_setting.namespace_stackable[:namespace] = Grape::Namespace.new(space, requirements:, **options) if space
|
|
229
|
+
end
|
|
199
230
|
end
|
|
231
|
+
end
|
|
200
232
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
233
|
+
alias group namespace
|
|
234
|
+
alias resource namespace
|
|
235
|
+
alias resources namespace
|
|
236
|
+
alias segment namespace
|
|
204
237
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
# @option options [Regexp] You may supply a regular expression that the declared parameter must meet.
|
|
210
|
-
def route_param(param, options = {}, &block)
|
|
211
|
-
options = options.dup
|
|
238
|
+
# An array of API routes.
|
|
239
|
+
def routes
|
|
240
|
+
@routes ||= endpoints.map(&:routes).flatten
|
|
241
|
+
end
|
|
212
242
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
243
|
+
# This method allows you to quickly define a parameter route segment
|
|
244
|
+
# in your API.
|
|
245
|
+
#
|
|
246
|
+
# @param param [Symbol] The name of the parameter you wish to declare.
|
|
247
|
+
# @option options [Regexp] You may supply a regular expression that the declared parameter must meet.
|
|
248
|
+
def route_param(param, requirements: nil, type: nil, **, &)
|
|
249
|
+
requirements = { param.to_sym => requirements } if requirements.is_a?(Regexp)
|
|
216
250
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
251
|
+
Grape::Validations::ParamsScope.new(api: self) do
|
|
252
|
+
requires param, type: type
|
|
253
|
+
end if type
|
|
220
254
|
|
|
221
|
-
|
|
222
|
-
|
|
255
|
+
namespace(":#{param}", requirements:, **, &)
|
|
256
|
+
end
|
|
223
257
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
258
|
+
# @return array of defined versions
|
|
259
|
+
def versions
|
|
260
|
+
@versions ||= []
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
private
|
|
264
|
+
|
|
265
|
+
# Remove all defined routes.
|
|
266
|
+
def reset_routes!
|
|
267
|
+
endpoints.each(&:reset_routes!)
|
|
268
|
+
@routes = nil
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def reset_endpoints!
|
|
272
|
+
@endpoints = []
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def refresh_mounted_api(mounts, *opts)
|
|
276
|
+
opts << { refresh_already_mounted: true }
|
|
277
|
+
mount(mounts, *opts)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Execute first the provided block, then each of the
|
|
281
|
+
# block passed in. Allows for simple 'before' setups
|
|
282
|
+
# of settings stack pushes.
|
|
283
|
+
def nest(*blocks, &block)
|
|
284
|
+
blocks.compact!
|
|
285
|
+
return instance_eval(&block) if blocks.empty?
|
|
286
|
+
|
|
287
|
+
evaluate_as_instance_with_configuration(block) if block
|
|
288
|
+
blocks.each { |b| evaluate_as_instance_with_configuration(b) }
|
|
289
|
+
reset_validations!
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def evaluate_as_instance_with_configuration(block, lazy: false)
|
|
293
|
+
lazy_block = Grape::Util::Lazy::Block.new do |configuration|
|
|
294
|
+
value_for_configuration = configuration
|
|
295
|
+
self.configuration = value_for_configuration.evaluate if value_for_configuration.is_a?(Grape::Util::Lazy::Base)
|
|
296
|
+
response = instance_eval(&block)
|
|
297
|
+
self.configuration = value_for_configuration
|
|
298
|
+
response
|
|
227
299
|
end
|
|
300
|
+
return lazy_block if @base && base_instance? && lazy
|
|
301
|
+
|
|
302
|
+
lazy_block.evaluate_from(configuration)
|
|
228
303
|
end
|
|
229
304
|
end
|
|
230
305
|
end
|