grape 1.2.5 → 1.4.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 +97 -0
 - data/LICENSE +1 -1
 - data/README.md +53 -16
 - data/UPGRADING.md +231 -23
 - data/grape.gemspec +10 -1
 - data/lib/grape.rb +6 -7
 - data/lib/grape/api.rb +4 -2
 - data/lib/grape/api/helpers.rb +2 -0
 - data/lib/grape/api/instance.rb +36 -33
 - data/lib/grape/config.rb +2 -0
 - data/lib/grape/content_types.rb +34 -0
 - data/lib/grape/cookies.rb +2 -0
 - data/lib/grape/dsl/api.rb +2 -0
 - data/lib/grape/dsl/callbacks.rb +2 -0
 - data/lib/grape/dsl/configuration.rb +2 -0
 - data/lib/grape/dsl/desc.rb +2 -0
 - data/lib/grape/dsl/headers.rb +2 -0
 - data/lib/grape/dsl/helpers.rb +4 -2
 - data/lib/grape/dsl/inside_route.rb +83 -34
 - data/lib/grape/dsl/logger.rb +2 -0
 - data/lib/grape/dsl/middleware.rb +2 -0
 - data/lib/grape/dsl/parameters.rb +8 -6
 - data/lib/grape/dsl/request_response.rb +4 -2
 - data/lib/grape/dsl/routing.rb +9 -5
 - data/lib/grape/dsl/settings.rb +7 -1
 - data/lib/grape/dsl/validations.rb +20 -1
 - data/lib/grape/eager_load.rb +3 -1
 - data/lib/grape/endpoint.rb +21 -13
 - data/lib/grape/error_formatter.rb +3 -1
 - data/lib/grape/error_formatter/base.rb +2 -0
 - data/lib/grape/error_formatter/json.rb +2 -0
 - data/lib/grape/error_formatter/txt.rb +2 -0
 - data/lib/grape/error_formatter/xml.rb +2 -0
 - data/lib/grape/exceptions/base.rb +11 -13
 - data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
 - data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
 - data/lib/grape/exceptions/invalid_formatter.rb +2 -0
 - data/lib/grape/exceptions/invalid_message_body.rb +2 -0
 - data/lib/grape/exceptions/invalid_response.rb +2 -0
 - data/lib/grape/exceptions/invalid_version_header.rb +2 -0
 - data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
 - data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
 - data/lib/grape/exceptions/method_not_allowed.rb +2 -0
 - data/lib/grape/exceptions/missing_group_type.rb +2 -0
 - data/lib/grape/exceptions/missing_mime_type.rb +2 -0
 - data/lib/grape/exceptions/missing_option.rb +2 -0
 - data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
 - data/lib/grape/exceptions/unknown_options.rb +2 -0
 - data/lib/grape/exceptions/unknown_parameter.rb +2 -0
 - data/lib/grape/exceptions/unknown_validator.rb +2 -0
 - data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
 - data/lib/grape/exceptions/validation.rb +3 -1
 - data/lib/grape/exceptions/validation_array_errors.rb +2 -0
 - data/lib/grape/exceptions/validation_errors.rb +13 -12
 - data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
 - data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
 - data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
 - data/lib/grape/extensions/hash.rb +2 -0
 - data/lib/grape/extensions/hashie/mash.rb +2 -0
 - data/lib/grape/formatter.rb +5 -3
 - data/lib/grape/formatter/json.rb +2 -0
 - data/lib/grape/formatter/serializable_hash.rb +2 -0
 - data/lib/grape/formatter/txt.rb +2 -0
 - data/lib/grape/formatter/xml.rb +2 -0
 - data/lib/grape/http/headers.rb +50 -18
 - data/lib/grape/middleware/auth/base.rb +2 -0
 - data/lib/grape/middleware/auth/dsl.rb +2 -0
 - data/lib/grape/middleware/auth/strategies.rb +2 -0
 - data/lib/grape/middleware/auth/strategy_info.rb +2 -0
 - data/lib/grape/middleware/base.rb +7 -7
 - data/lib/grape/middleware/error.rb +3 -1
 - data/lib/grape/middleware/filter.rb +2 -0
 - data/lib/grape/middleware/formatter.rb +8 -6
 - data/lib/grape/middleware/globals.rb +2 -0
 - data/lib/grape/middleware/helpers.rb +2 -0
 - data/lib/grape/middleware/stack.rb +4 -1
 - data/lib/grape/middleware/versioner.rb +2 -0
 - data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
 - data/lib/grape/middleware/versioner/header.rb +6 -4
 - data/lib/grape/middleware/versioner/param.rb +3 -1
 - data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
 - data/lib/grape/middleware/versioner/path.rb +3 -1
 - data/lib/grape/namespace.rb +14 -2
 - data/lib/grape/parser.rb +3 -1
 - data/lib/grape/parser/json.rb +2 -0
 - data/lib/grape/parser/xml.rb +2 -0
 - data/lib/grape/path.rb +15 -3
 - data/lib/grape/presenters/presenter.rb +2 -0
 - data/lib/grape/request.rb +15 -8
 - data/lib/grape/router.rb +30 -29
 - data/lib/grape/router/attribute_translator.rb +39 -8
 - data/lib/grape/router/pattern.rb +20 -16
 - data/lib/grape/router/route.rb +12 -26
 - data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
 - data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
 - data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
 - data/lib/grape/util/base_inheritable.rb +15 -6
 - data/lib/grape/util/cache.rb +20 -0
 - data/lib/grape/util/endpoint_configuration.rb +2 -0
 - data/lib/grape/util/env.rb +19 -17
 - data/lib/grape/util/inheritable_setting.rb +2 -0
 - data/lib/grape/util/inheritable_values.rb +2 -0
 - data/lib/grape/util/json.rb +2 -0
 - data/lib/grape/util/lazy_block.rb +2 -0
 - data/lib/grape/util/lazy_object.rb +43 -0
 - data/lib/grape/util/lazy_value.rb +2 -0
 - data/lib/grape/util/registrable.rb +2 -0
 - data/lib/grape/util/reverse_stackable_values.rb +4 -0
 - data/lib/grape/util/stackable_values.rb +10 -20
 - data/lib/grape/util/strict_hash_configuration.rb +2 -0
 - data/lib/grape/util/xml.rb +2 -0
 - data/lib/grape/validations.rb +2 -0
 - data/lib/grape/validations/attributes_iterator.rb +3 -3
 - data/lib/grape/validations/multiple_attributes_iterator.rb +2 -0
 - data/lib/grape/validations/params_scope.rb +27 -14
 - data/lib/grape/validations/single_attribute_iterator.rb +13 -2
 - data/lib/grape/validations/types.rb +12 -34
 - data/lib/grape/validations/types/array_coercer.rb +65 -0
 - data/lib/grape/validations/types/build_coercer.rb +47 -49
 - data/lib/grape/validations/types/custom_type_coercer.rb +15 -49
 - data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
 - data/lib/grape/validations/types/dry_type_coercer.rb +76 -0
 - data/lib/grape/validations/types/file.rb +22 -18
 - data/lib/grape/validations/types/json.rb +46 -39
 - data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
 - data/lib/grape/validations/types/primitive_coercer.rb +67 -0
 - data/lib/grape/validations/types/set_coercer.rb +40 -0
 - data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
 - data/lib/grape/validations/validator_factory.rb +2 -0
 - data/lib/grape/validations/validators/all_or_none.rb +3 -1
 - data/lib/grape/validations/validators/allow_blank.rb +3 -1
 - data/lib/grape/validations/validators/as.rb +2 -0
 - data/lib/grape/validations/validators/at_least_one_of.rb +3 -1
 - data/lib/grape/validations/validators/base.rb +8 -5
 - data/lib/grape/validations/validators/coerce.rb +39 -29
 - data/lib/grape/validations/validators/default.rb +2 -1
 - data/lib/grape/validations/validators/exactly_one_of.rb +6 -2
 - data/lib/grape/validations/validators/except_values.rb +3 -1
 - data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
 - data/lib/grape/validations/validators/mutual_exclusion.rb +3 -1
 - data/lib/grape/validations/validators/presence.rb +3 -1
 - data/lib/grape/validations/validators/regexp.rb +4 -2
 - data/lib/grape/validations/validators/same_as.rb +6 -3
 - data/lib/grape/validations/validators/values.rb +17 -5
 - data/lib/grape/version.rb +3 -1
 - data/spec/grape/api/custom_validations_spec.rb +5 -3
 - data/spec/grape/api/deeply_included_options_spec.rb +2 -0
 - data/spec/grape/api/defines_boolean_in_params_spec.rb +5 -3
 - data/spec/grape/api/inherited_helpers_spec.rb +2 -0
 - data/spec/grape/api/instance_spec.rb +104 -0
 - data/spec/grape/api/invalid_format_spec.rb +2 -0
 - data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
 - data/spec/grape/api/nested_helpers_spec.rb +2 -0
 - data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
 - data/spec/grape/api/parameters_modification_spec.rb +3 -1
 - data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
 - data/spec/grape/api/recognize_path_spec.rb +2 -0
 - data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
 - data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
 - data/spec/grape/api/routes_with_requirements_spec.rb +2 -0
 - data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
 - data/spec/grape/api/shared_helpers_spec.rb +2 -0
 - data/spec/grape/api_remount_spec.rb +2 -0
 - data/spec/grape/api_spec.rb +99 -11
 - data/spec/grape/config_spec.rb +2 -0
 - data/spec/grape/dsl/callbacks_spec.rb +2 -0
 - data/spec/grape/dsl/configuration_spec.rb +2 -0
 - data/spec/grape/dsl/desc_spec.rb +2 -0
 - data/spec/grape/dsl/headers_spec.rb +2 -0
 - data/spec/grape/dsl/helpers_spec.rb +4 -2
 - data/spec/grape/dsl/inside_route_spec.rb +177 -33
 - data/spec/grape/dsl/logger_spec.rb +2 -0
 - data/spec/grape/dsl/middleware_spec.rb +2 -0
 - data/spec/grape/dsl/parameters_spec.rb +2 -0
 - data/spec/grape/dsl/request_response_spec.rb +2 -0
 - data/spec/grape/dsl/routing_spec.rb +2 -0
 - data/spec/grape/dsl/settings_spec.rb +2 -0
 - data/spec/grape/dsl/validations_spec.rb +2 -0
 - data/spec/grape/endpoint_spec.rb +21 -6
 - data/spec/grape/entity_spec.rb +2 -0
 - data/spec/grape/exceptions/base_spec.rb +3 -1
 - data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
 - data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
 - data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
 - data/spec/grape/exceptions/invalid_response_spec.rb +2 -0
 - data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
 - data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
 - data/spec/grape/exceptions/missing_option_spec.rb +2 -0
 - data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
 - data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
 - data/spec/grape/exceptions/validation_errors_spec.rb +4 -2
 - data/spec/grape/exceptions/validation_spec.rb +3 -1
 - data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
 - data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
 - data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
 - data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
 - data/spec/grape/integration/rack_sendfile_spec.rb +14 -8
 - data/spec/grape/integration/rack_spec.rb +3 -1
 - data/spec/grape/loading_spec.rb +2 -0
 - data/spec/grape/middleware/auth/base_spec.rb +2 -0
 - data/spec/grape/middleware/auth/dsl_spec.rb +2 -0
 - data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
 - data/spec/grape/middleware/base_spec.rb +2 -0
 - data/spec/grape/middleware/error_spec.rb +2 -0
 - data/spec/grape/middleware/exception_spec.rb +3 -1
 - data/spec/grape/middleware/formatter_spec.rb +19 -12
 - data/spec/grape/middleware/globals_spec.rb +2 -0
 - data/spec/grape/middleware/stack_spec.rb +11 -0
 - data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
 - data/spec/grape/middleware/versioner/header_spec.rb +3 -1
 - data/spec/grape/middleware/versioner/param_spec.rb +3 -1
 - data/spec/grape/middleware/versioner/path_spec.rb +3 -1
 - data/spec/grape/middleware/versioner_spec.rb +2 -0
 - data/spec/grape/named_api_spec.rb +2 -0
 - data/spec/grape/parser_spec.rb +7 -5
 - data/spec/grape/path_spec.rb +6 -4
 - data/spec/grape/presenters/presenter_spec.rb +2 -0
 - data/spec/grape/request_spec.rb +2 -0
 - data/spec/grape/util/inheritable_setting_spec.rb +2 -0
 - data/spec/grape/util/inheritable_values_spec.rb +2 -0
 - data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
 - data/spec/grape/util/stackable_values_spec.rb +3 -1
 - data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
 - data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
 - data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
 - data/spec/grape/validations/multiple_attributes_iterator_spec.rb +2 -0
 - data/spec/grape/validations/params_scope_spec.rb +3 -1
 - data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -4
 - data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
 - data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
 - data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
 - data/spec/grape/validations/types_spec.rb +9 -36
 - data/spec/grape/validations/validators/all_or_none_spec.rb +2 -0
 - data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
 - data/spec/grape/validations/validators/at_least_one_of_spec.rb +2 -0
 - data/spec/grape/validations/validators/coerce_spec.rb +341 -136
 - data/spec/grape/validations/validators/default_spec.rb +123 -0
 - data/spec/grape/validations/validators/exactly_one_of_spec.rb +14 -12
 - data/spec/grape/validations/validators/except_values_spec.rb +3 -1
 - data/spec/grape/validations/validators/mutual_exclusion_spec.rb +2 -0
 - data/spec/grape/validations/validators/presence_spec.rb +30 -0
 - data/spec/grape/validations/validators/regexp_spec.rb +2 -0
 - data/spec/grape/validations/validators/same_as_spec.rb +2 -0
 - data/spec/grape/validations/validators/values_spec.rb +30 -5
 - data/spec/grape/validations_spec.rb +91 -33
 - data/spec/integration/eager_load/eager_load_spec.rb +15 -0
 - data/spec/integration/multi_json/json_spec.rb +2 -0
 - data/spec/integration/multi_xml/xml_spec.rb +2 -0
 - data/spec/shared/versioning_examples.rb +2 -0
 - data/spec/spec_helper.rb +18 -0
 - data/spec/support/basic_auth_encode_helpers.rb +2 -0
 - data/spec/support/content_type_helpers.rb +2 -0
 - data/spec/support/eager_load.rb +19 -0
 - data/spec/support/endpoint_faker.rb +2 -0
 - data/spec/support/file_streamer.rb +2 -0
 - data/spec/support/integer_helpers.rb +2 -0
 - data/spec/support/versioned_helpers.rb +4 -2
 - metadata +48 -28
 - data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
 - data/lib/grape/util/content_types.rb +0 -26
 - data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
 
    
        data/grape.gemspec
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
         
     | 
| 
       2 
4 
     | 
    
         
             
            require 'grape/version'
         
     | 
| 
       3 
5 
     | 
    
         | 
| 
         @@ -11,17 +13,24 @@ Gem::Specification.new do |s| 
     | 
|
| 
       11 
13 
     | 
    
         
             
              s.summary     = 'A simple Ruby framework for building REST-like APIs.'
         
     | 
| 
       12 
14 
     | 
    
         
             
              s.description = 'A Ruby framework for rapid API development with great conventions.'
         
     | 
| 
       13 
15 
     | 
    
         
             
              s.license     = 'MIT'
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.metadata    = {
         
     | 
| 
      
 17 
     | 
    
         
            +
                'bug_tracker_uri'   => 'https://github.com/ruby-grape/grape/issues',
         
     | 
| 
      
 18 
     | 
    
         
            +
                'changelog_uri'     => "https://github.com/ruby-grape/grape/blob/v#{s.version}/CHANGELOG.md",
         
     | 
| 
      
 19 
     | 
    
         
            +
                'documentation_uri' => "https://www.rubydoc.info/gems/grape/#{s.version}",
         
     | 
| 
      
 20 
     | 
    
         
            +
                'source_code_uri'   => "https://github.com/ruby-grape/grape/tree/v#{s.version}"
         
     | 
| 
      
 21 
     | 
    
         
            +
              }
         
     | 
| 
       14 
22 
     | 
    
         | 
| 
       15 
23 
     | 
    
         
             
              s.add_runtime_dependency 'activesupport'
         
     | 
| 
       16 
24 
     | 
    
         
             
              s.add_runtime_dependency 'builder'
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.add_runtime_dependency 'dry-types', '>= 1.1'
         
     | 
| 
       17 
26 
     | 
    
         
             
              s.add_runtime_dependency 'mustermann-grape', '~> 1.0.0'
         
     | 
| 
       18 
27 
     | 
    
         
             
              s.add_runtime_dependency 'rack', '>= 1.3.0'
         
     | 
| 
       19 
28 
     | 
    
         
             
              s.add_runtime_dependency 'rack-accept'
         
     | 
| 
       20 
     | 
    
         
            -
              s.add_runtime_dependency 'virtus', '>= 1.0.0'
         
     | 
| 
       21 
29 
     | 
    
         | 
| 
       22 
30 
     | 
    
         
             
              s.files         = %w[CHANGELOG.md CONTRIBUTING.md README.md grape.png UPGRADING.md LICENSE]
         
     | 
| 
       23 
31 
     | 
    
         
             
              s.files        += %w[grape.gemspec]
         
     | 
| 
       24 
32 
     | 
    
         
             
              s.files        += Dir['lib/**/*']
         
     | 
| 
       25 
33 
     | 
    
         
             
              s.test_files    = Dir['spec/**/*']
         
     | 
| 
       26 
34 
     | 
    
         
             
              s.require_paths = ['lib']
         
     | 
| 
      
 35 
     | 
    
         
            +
              s.required_ruby_version = '>= 2.4.0'
         
     | 
| 
       27 
36 
     | 
    
         
             
            end
         
     | 
    
        data/lib/grape.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'logger'
         
     | 
| 
       2 
4 
     | 
    
         
             
            require 'rack'
         
     | 
| 
       3 
5 
     | 
    
         
             
            require 'rack/builder'
         
     | 
| 
         @@ -18,9 +20,6 @@ require 'active_support/core_ext/hash/conversions' 
     | 
|
| 
       18 
20 
     | 
    
         
             
            require 'active_support/dependencies/autoload'
         
     | 
| 
       19 
21 
     | 
    
         
             
            require 'active_support/notifications'
         
     | 
| 
       20 
22 
     | 
    
         
             
            require 'i18n'
         
     | 
| 
       21 
     | 
    
         
            -
            require 'thread'
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
            require 'virtus'
         
     | 
| 
       24 
23 
     | 
    
         | 
| 
       25 
24 
     | 
    
         
             
            I18n.load_path << File.expand_path('../grape/locale/en.yml', __FILE__)
         
     | 
| 
       26 
25 
     | 
    
         | 
| 
         @@ -84,7 +83,6 @@ module Grape 
     | 
|
| 
       84 
83 
     | 
    
         
             
                eager_autoload do
         
     | 
| 
       85 
84 
     | 
    
         
             
                  autoload :DeepMergeableHash
         
     | 
| 
       86 
85 
     | 
    
         
             
                  autoload :DeepSymbolizeHash
         
     | 
| 
       87 
     | 
    
         
            -
                  autoload :DeepHashWithIndifferentAccess
         
     | 
| 
       88 
86 
     | 
    
         
             
                  autoload :Hash
         
     | 
| 
       89 
87 
     | 
    
         
             
                end
         
     | 
| 
       90 
88 
     | 
    
         
             
                module ActiveSupport
         
     | 
| 
         @@ -208,18 +206,19 @@ module Grape 
     | 
|
| 
       208 
206 
     | 
    
         
             
                end
         
     | 
| 
       209 
207 
     | 
    
         
             
              end
         
     | 
| 
       210 
208 
     | 
    
         | 
| 
       211 
     | 
    
         
            -
              module  
     | 
| 
      
 209 
     | 
    
         
            +
              module ServeStream
         
     | 
| 
       212 
210 
     | 
    
         
             
                extend ::ActiveSupport::Autoload
         
     | 
| 
       213 
211 
     | 
    
         
             
                eager_autoload do
         
     | 
| 
       214 
     | 
    
         
            -
                  autoload :FileResponse
         
     | 
| 
       215 
212 
     | 
    
         
             
                  autoload :FileBody
         
     | 
| 
       216 
213 
     | 
    
         
             
                  autoload :SendfileResponse
         
     | 
| 
      
 214 
     | 
    
         
            +
                  autoload :StreamResponse
         
     | 
| 
       217 
215 
     | 
    
         
             
                end
         
     | 
| 
       218 
216 
     | 
    
         
             
              end
         
     | 
| 
       219 
217 
     | 
    
         
             
            end
         
     | 
| 
       220 
218 
     | 
    
         | 
| 
       221 
219 
     | 
    
         
             
            require 'grape/config'
         
     | 
| 
       222 
     | 
    
         
            -
            require 'grape/ 
     | 
| 
      
 220 
     | 
    
         
            +
            require 'grape/content_types'
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
       223 
222 
     | 
    
         
             
            require 'grape/util/lazy_value'
         
     | 
| 
       224 
223 
     | 
    
         
             
            require 'grape/util/lazy_block'
         
     | 
| 
       225 
224 
     | 
    
         
             
            require 'grape/util/endpoint_configuration'
         
     | 
    
        data/lib/grape/api.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'grape/router'
         
     | 
| 
       2 
4 
     | 
    
         
             
            require 'grape/api/instance'
         
     | 
| 
       3 
5 
     | 
    
         | 
| 
         @@ -6,7 +8,7 @@ module Grape 
     | 
|
| 
       6 
8 
     | 
    
         
             
              # should subclass this class in order to build an API.
         
     | 
| 
       7 
9 
     | 
    
         
             
              class API
         
     | 
| 
       8 
10 
     | 
    
         
             
                # Class methods that we want to call on the API rather than on the API object
         
     | 
| 
       9 
     | 
    
         
            -
                NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile!]).freeze
         
     | 
| 
      
 11 
     | 
    
         
            +
                NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile! inherited]).freeze
         
     | 
| 
       10 
12 
     | 
    
         | 
| 
       11 
13 
     | 
    
         
             
                class << self
         
     | 
| 
       12 
14 
     | 
    
         
             
                  attr_accessor :base_instance, :instances
         
     | 
| 
         @@ -173,7 +175,7 @@ module Grape 
     | 
|
| 
       173 
175 
     | 
    
         
             
                      if argument.respond_to?(:lazy?) && argument.lazy?
         
     | 
| 
       174 
176 
     | 
    
         
             
                        argument.evaluate_from(configuration)
         
     | 
| 
       175 
177 
     | 
    
         
             
                      elsif argument.is_a?(Hash)
         
     | 
| 
       176 
     | 
    
         
            -
                        argument. 
     | 
| 
      
 178 
     | 
    
         
            +
                        argument.transform_values { |value| evaluate_arguments(configuration, value).first }
         
     | 
| 
       177 
179 
     | 
    
         
             
                      elsif argument.is_a?(Array)
         
     | 
| 
       178 
180 
     | 
    
         
             
                        evaluate_arguments(configuration, *argument)
         
     | 
| 
       179 
181 
     | 
    
         
             
                      else
         
     | 
    
        data/lib/grape/api/helpers.rb
    CHANGED
    
    
    
        data/lib/grape/api/instance.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'grape/router'
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
            module Grape
         
     | 
| 
         @@ -72,7 +74,7 @@ module Grape 
     | 
|
| 
       72 
74 
     | 
    
         
             
                    # (see #cascade?)
         
     | 
| 
       73 
75 
     | 
    
         
             
                    def cascade(value = nil)
         
     | 
| 
       74 
76 
     | 
    
         
             
                      if value.nil?
         
     | 
| 
       75 
     | 
    
         
            -
                        inheritable_setting.namespace_inheritable. 
     | 
| 
      
 77 
     | 
    
         
            +
                        inheritable_setting.namespace_inheritable.key?(:cascade) ? !namespace_inheritable(:cascade).nil? : true
         
     | 
| 
       76 
78 
     | 
    
         
             
                      else
         
     | 
| 
       77 
79 
     | 
    
         
             
                        namespace_inheritable(:cascade, value)
         
     | 
| 
       78 
80 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -119,7 +121,7 @@ module Grape 
     | 
|
| 
       119 
121 
     | 
    
         
             
                        self.configuration = value_for_configuration
         
     | 
| 
       120 
122 
     | 
    
         
             
                        response
         
     | 
| 
       121 
123 
     | 
    
         
             
                      end
         
     | 
| 
       122 
     | 
    
         
            -
                      if base_instance? && lazy
         
     | 
| 
      
 124 
     | 
    
         
            +
                      if base && base_instance? && lazy
         
     | 
| 
       123 
125 
     | 
    
         
             
                        lazy_block
         
     | 
| 
       124 
126 
     | 
    
         
             
                      else
         
     | 
| 
       125 
127 
     | 
    
         
             
                        lazy_block.evaluate_from(configuration)
         
     | 
| 
         @@ -176,7 +178,7 @@ module Grape 
     | 
|
| 
       176 
178 
     | 
    
         
             
                  # errors from reaching upstream. This is effectivelly done by unsetting
         
     | 
| 
       177 
179 
     | 
    
         
             
                  # X-Cascade. Default :cascade is true.
         
     | 
| 
       178 
180 
     | 
    
         
             
                  def cascade?
         
     | 
| 
       179 
     | 
    
         
            -
                    return self.class.namespace_inheritable(:cascade) if self.class.inheritable_setting.namespace_inheritable. 
     | 
| 
      
 181 
     | 
    
         
            +
                    return self.class.namespace_inheritable(:cascade) if self.class.inheritable_setting.namespace_inheritable.key?(:cascade)
         
     | 
| 
       180 
182 
     | 
    
         
             
                    return self.class.namespace_inheritable(:version_options)[:cascade] if self.class.namespace_inheritable(:version_options) && self.class.namespace_inheritable(:version_options).key?(:cascade)
         
     | 
| 
       181 
183 
     | 
    
         
             
                    true
         
     | 
| 
       182 
184 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -190,62 +192,63 @@ module Grape 
     | 
|
| 
       190 
192 
     | 
    
         
             
                  # will return an HTTP 405 response for any HTTP method that the resource
         
     | 
| 
       191 
193 
     | 
    
         
             
                  # cannot handle.
         
     | 
| 
       192 
194 
     | 
    
         
             
                  def add_head_not_allowed_methods_and_options_methods
         
     | 
| 
       193 
     | 
    
         
            -
                     
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
                    self.class.endpoints.each do |endpoint|
         
     | 
| 
       196 
     | 
    
         
            -
                      routes = endpoint.routes
         
     | 
| 
       197 
     | 
    
         
            -
                      routes.each do |route|
         
     | 
| 
       198 
     | 
    
         
            -
                        # using the :any shorthand produces [nil] for route methods, substitute all manually
         
     | 
| 
       199 
     | 
    
         
            -
                        route_key = route.pattern.to_regexp
         
     | 
| 
       200 
     | 
    
         
            -
                        routes_map[route_key] ||= {}
         
     | 
| 
       201 
     | 
    
         
            -
                        route_settings = routes_map[route_key]
         
     | 
| 
       202 
     | 
    
         
            -
                        route_settings[:pattern] = route.pattern
         
     | 
| 
       203 
     | 
    
         
            -
                        route_settings[:requirements] = route.requirements
         
     | 
| 
       204 
     | 
    
         
            -
                        route_settings[:path] = route.origin
         
     | 
| 
       205 
     | 
    
         
            -
                        route_settings[:methods] ||= []
         
     | 
| 
       206 
     | 
    
         
            -
                        route_settings[:methods] << route.request_method
         
     | 
| 
       207 
     | 
    
         
            -
                        route_settings[:endpoint] = route.app
         
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
                        # using the :any shorthand produces [nil] for route methods, substitute all manually
         
     | 
| 
       210 
     | 
    
         
            -
                        route_settings[:methods] = %w[GET PUT POST DELETE PATCH HEAD OPTIONS] if route_settings[:methods].include?('*')
         
     | 
| 
       211 
     | 
    
         
            -
                      end
         
     | 
| 
       212 
     | 
    
         
            -
                    end
         
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
      
 195 
     | 
    
         
            +
                    versioned_route_configs = collect_route_config_per_pattern
         
     | 
| 
       214 
196 
     | 
    
         
             
                    # The paths we collected are prepared (cf. Path#prepare), so they
         
     | 
| 
       215 
197 
     | 
    
         
             
                    # contain already versioning information when using path versioning.
         
     | 
| 
       216 
198 
     | 
    
         
             
                    # Disable versioning so adding a route won't prepend versioning
         
     | 
| 
       217 
199 
     | 
    
         
             
                    # informations again.
         
     | 
| 
       218 
200 
     | 
    
         
             
                    without_root_prefix do
         
     | 
| 
       219 
201 
     | 
    
         
             
                      without_versioning do
         
     | 
| 
       220 
     | 
    
         
            -
                         
     | 
| 
       221 
     | 
    
         
            -
                           
     | 
| 
       222 
     | 
    
         
            -
                          allowed_methods = methods.dup
         
     | 
| 
      
 202 
     | 
    
         
            +
                        versioned_route_configs.each do |config|
         
     | 
| 
      
 203 
     | 
    
         
            +
                          allowed_methods = config[:methods].dup
         
     | 
| 
       223 
204 
     | 
    
         | 
| 
       224 
205 
     | 
    
         
             
                          unless self.class.namespace_inheritable(:do_not_route_head)
         
     | 
| 
       225 
206 
     | 
    
         
             
                            allowed_methods |= [Grape::Http::Headers::HEAD] if allowed_methods.include?(Grape::Http::Headers::GET)
         
     | 
| 
       226 
207 
     | 
    
         
             
                          end
         
     | 
| 
       227 
208 
     | 
    
         | 
| 
       228 
     | 
    
         
            -
                          allow_header = (self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Grape::Http::Headers::OPTIONS] | allowed_methods) 
     | 
| 
      
 209 
     | 
    
         
            +
                          allow_header = (self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Grape::Http::Headers::OPTIONS] | allowed_methods)
         
     | 
| 
       229 
210 
     | 
    
         | 
| 
       230 
211 
     | 
    
         
             
                          unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Grape::Http::Headers::OPTIONS)
         
     | 
| 
       231 
212 
     | 
    
         
             
                            config[:endpoint].options[:options_route_enabled] = true
         
     | 
| 
       232 
213 
     | 
    
         
             
                          end
         
     | 
| 
       233 
214 
     | 
    
         | 
| 
       234 
215 
     | 
    
         
             
                          attributes = config.merge(allowed_methods: allowed_methods, allow_header: allow_header)
         
     | 
| 
       235 
     | 
    
         
            -
                          generate_not_allowed_method(config[:pattern], attributes)
         
     | 
| 
      
 216 
     | 
    
         
            +
                          generate_not_allowed_method(config[:pattern], **attributes)
         
     | 
| 
       236 
217 
     | 
    
         
             
                        end
         
     | 
| 
       237 
218 
     | 
    
         
             
                      end
         
     | 
| 
       238 
219 
     | 
    
         
             
                    end
         
     | 
| 
       239 
220 
     | 
    
         
             
                  end
         
     | 
| 
       240 
221 
     | 
    
         | 
| 
      
 222 
     | 
    
         
            +
                  def collect_route_config_per_pattern
         
     | 
| 
      
 223 
     | 
    
         
            +
                    all_routes       = self.class.endpoints.map(&:routes).flatten
         
     | 
| 
      
 224 
     | 
    
         
            +
                    routes_by_regexp = all_routes.group_by { |route| route.pattern.to_regexp }
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                    # Build the configuration based on the first endpoint and the collection of methods supported.
         
     | 
| 
      
 227 
     | 
    
         
            +
                    routes_by_regexp.values.map do |routes|
         
     | 
| 
      
 228 
     | 
    
         
            +
                      last_route        = routes.last # Most of the configuration is taken from the last endpoint
         
     | 
| 
      
 229 
     | 
    
         
            +
                      matching_wildchar = routes.any? { |route| route.request_method == '*' }
         
     | 
| 
      
 230 
     | 
    
         
            +
                      {
         
     | 
| 
      
 231 
     | 
    
         
            +
                        options: {},
         
     | 
| 
      
 232 
     | 
    
         
            +
                        pattern: last_route.pattern,
         
     | 
| 
      
 233 
     | 
    
         
            +
                        requirements: last_route.requirements,
         
     | 
| 
      
 234 
     | 
    
         
            +
                        path: last_route.origin,
         
     | 
| 
      
 235 
     | 
    
         
            +
                        endpoint: last_route.app,
         
     | 
| 
      
 236 
     | 
    
         
            +
                        methods: matching_wildchar ? Grape::Http::Headers::SUPPORTED_METHODS : routes.map(&:request_method)
         
     | 
| 
      
 237 
     | 
    
         
            +
                      }
         
     | 
| 
      
 238 
     | 
    
         
            +
                    end
         
     | 
| 
      
 239 
     | 
    
         
            +
                  end
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
       241 
241 
     | 
    
         
             
                  # Generate a route that returns an HTTP 405 response for a user defined
         
     | 
| 
       242 
242 
     | 
    
         
             
                  # path on methods not specified
         
     | 
| 
       243 
243 
     | 
    
         
             
                  def generate_not_allowed_method(pattern, allowed_methods: [], **attributes)
         
     | 
| 
       244 
     | 
    
         
            -
                     
     | 
| 
       245 
     | 
    
         
            -
             
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
      
 244 
     | 
    
         
            +
                    supported_methods =
         
     | 
| 
      
 245 
     | 
    
         
            +
                      if self.class.namespace_inheritable(:do_not_route_options)
         
     | 
| 
      
 246 
     | 
    
         
            +
                        Grape::Http::Headers::SUPPORTED_METHODS
         
     | 
| 
      
 247 
     | 
    
         
            +
                      else
         
     | 
| 
      
 248 
     | 
    
         
            +
                        Grape::Http::Headers::SUPPORTED_METHODS_WITHOUT_OPTIONS
         
     | 
| 
      
 249 
     | 
    
         
            +
                      end
         
     | 
| 
      
 250 
     | 
    
         
            +
                    not_allowed_methods = supported_methods - allowed_methods
         
     | 
| 
       247 
251 
     | 
    
         
             
                    return if not_allowed_methods.empty?
         
     | 
| 
       248 
     | 
    
         
            -
             
     | 
| 
       249 
252 
     | 
    
         
             
                    @router.associate_routes(pattern, not_allowed_methods: not_allowed_methods, **attributes)
         
     | 
| 
       250 
253 
     | 
    
         
             
                  end
         
     | 
| 
       251 
254 
     | 
    
         | 
    
        data/lib/grape/config.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'grape/util/registrable'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Grape
         
     | 
| 
      
 6 
     | 
    
         
            +
              module ContentTypes
         
     | 
| 
      
 7 
     | 
    
         
            +
                extend Util::Registrable
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Content types are listed in order of preference.
         
     | 
| 
      
 10 
     | 
    
         
            +
                CONTENT_TYPES = {
         
     | 
| 
      
 11 
     | 
    
         
            +
                  xml: 'application/xml',
         
     | 
| 
      
 12 
     | 
    
         
            +
                  serializable_hash: 'application/json',
         
     | 
| 
      
 13 
     | 
    
         
            +
                  json: 'application/json',
         
     | 
| 
      
 14 
     | 
    
         
            +
                  binary: 'application/octet-stream',
         
     | 
| 
      
 15 
     | 
    
         
            +
                  txt: 'text/plain'
         
     | 
| 
      
 16 
     | 
    
         
            +
                }.freeze
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def content_types_for_settings(settings)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    return if settings.blank?
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    settings.each_with_object({}) { |value, result| result.merge!(value) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def content_types_for(from_settings)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if from_settings.present?
         
     | 
| 
      
 27 
     | 
    
         
            +
                      from_settings
         
     | 
| 
      
 28 
     | 
    
         
            +
                    else
         
     | 
| 
      
 29 
     | 
    
         
            +
                      Grape::ContentTypes::CONTENT_TYPES.merge(default_elements)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/grape/cookies.rb
    CHANGED
    
    
    
        data/lib/grape/dsl/api.rb
    CHANGED
    
    
    
        data/lib/grape/dsl/callbacks.rb
    CHANGED
    
    
    
        data/lib/grape/dsl/desc.rb
    CHANGED
    
    
    
        data/lib/grape/dsl/headers.rb
    CHANGED
    
    
    
        data/lib/grape/dsl/helpers.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'active_support/concern'
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
            module Grape
         
     | 
| 
         @@ -65,7 +67,7 @@ module Grape 
     | 
|
| 
       65 
67 
     | 
    
         | 
| 
       66 
68 
     | 
    
         
             
                    def define_boolean_in_mod(mod)
         
     | 
| 
       67 
69 
     | 
    
         
             
                      return if defined? mod::Boolean
         
     | 
| 
       68 
     | 
    
         
            -
                      mod.const_set('Boolean',  
     | 
| 
      
 70 
     | 
    
         
            +
                      mod.const_set('Boolean', Grape::API::Boolean)
         
     | 
| 
       69 
71 
     | 
    
         
             
                    end
         
     | 
| 
       70 
72 
     | 
    
         | 
| 
       71 
73 
     | 
    
         
             
                    def inject_api_helpers_to_mod(mod, &_block)
         
     | 
| 
         @@ -92,7 +94,7 @@ module Grape 
     | 
|
| 
       92 
94 
     | 
    
         
             
                    protected
         
     | 
| 
       93 
95 
     | 
    
         | 
| 
       94 
96 
     | 
    
         
             
                    def process_named_params
         
     | 
| 
       95 
     | 
    
         
            -
                      return unless @named_params && @named_params.any?
         
     | 
| 
      
 97 
     | 
    
         
            +
                      return unless instance_variable_defined?(:@named_params) && @named_params && @named_params.any?
         
     | 
| 
       96 
98 
     | 
    
         
             
                      api.namespace_stackable(:named_params, @named_params)
         
     | 
| 
       97 
99 
     | 
    
         
             
                    end
         
     | 
| 
       98 
100 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'active_support/concern'
         
     | 
| 
       2 
4 
     | 
    
         
             
            require 'grape/dsl/headers'
         
     | 
| 
       3 
5 
     | 
    
         | 
| 
         @@ -26,36 +28,38 @@ module Grape 
     | 
|
| 
       26 
28 
     | 
    
         
             
                  # Methods which should not be available in filters until the before filter
         
     | 
| 
       27 
29 
     | 
    
         
             
                  # has completed
         
     | 
| 
       28 
30 
     | 
    
         
             
                  module PostBeforeFilter
         
     | 
| 
       29 
     | 
    
         
            -
                    def declared(passed_params, options = {}, declared_params = nil)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    def declared(passed_params, options = {}, declared_params = nil, params_nested_path = [])
         
     | 
| 
       30 
32 
     | 
    
         
             
                      options = options.reverse_merge(include_missing: true, include_parent_namespaces: true)
         
     | 
| 
       31 
     | 
    
         
            -
                      declared_params ||= optioned_declared_params(options)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      declared_params ||= optioned_declared_params(**options)
         
     | 
| 
       32 
34 
     | 
    
         | 
| 
       33 
35 
     | 
    
         
             
                      if passed_params.is_a?(Array)
         
     | 
| 
       34 
     | 
    
         
            -
                        declared_array(passed_params, options, declared_params)
         
     | 
| 
      
 36 
     | 
    
         
            +
                        declared_array(passed_params, options, declared_params, params_nested_path)
         
     | 
| 
       35 
37 
     | 
    
         
             
                      else
         
     | 
| 
       36 
     | 
    
         
            -
                        declared_hash(passed_params, options, declared_params)
         
     | 
| 
      
 38 
     | 
    
         
            +
                        declared_hash(passed_params, options, declared_params, params_nested_path)
         
     | 
| 
       37 
39 
     | 
    
         
             
                      end
         
     | 
| 
       38 
40 
     | 
    
         
             
                    end
         
     | 
| 
       39 
41 
     | 
    
         | 
| 
       40 
42 
     | 
    
         
             
                    private
         
     | 
| 
       41 
43 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                    def declared_array(passed_params, options, declared_params)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    def declared_array(passed_params, options, declared_params, params_nested_path)
         
     | 
| 
       43 
45 
     | 
    
         
             
                      passed_params.map do |passed_param|
         
     | 
| 
       44 
     | 
    
         
            -
                        declared(passed_param || {}, options, declared_params)
         
     | 
| 
      
 46 
     | 
    
         
            +
                        declared(passed_param || {}, options, declared_params, params_nested_path)
         
     | 
| 
       45 
47 
     | 
    
         
             
                      end
         
     | 
| 
       46 
48 
     | 
    
         
             
                    end
         
     | 
| 
       47 
49 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                    def declared_hash(passed_params, options, declared_params)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    def declared_hash(passed_params, options, declared_params, params_nested_path)
         
     | 
| 
       49 
51 
     | 
    
         
             
                      declared_params.each_with_object(passed_params.class.new) do |declared_param, memo|
         
     | 
| 
       50 
52 
     | 
    
         
             
                        if declared_param.is_a?(Hash)
         
     | 
| 
       51 
53 
     | 
    
         
             
                          declared_param.each_pair do |declared_parent_param, declared_children_params|
         
     | 
| 
      
 54 
     | 
    
         
            +
                            params_nested_path_dup = params_nested_path.dup
         
     | 
| 
      
 55 
     | 
    
         
            +
                            params_nested_path_dup << declared_parent_param.to_s
         
     | 
| 
       52 
56 
     | 
    
         
             
                            next unless options[:include_missing] || passed_params.key?(declared_parent_param)
         
     | 
| 
       53 
57 
     | 
    
         | 
| 
       54 
58 
     | 
    
         
             
                            passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
         
     | 
| 
       55 
59 
     | 
    
         
             
                            memo_key = optioned_param_key(declared_parent_param, options)
         
     | 
| 
       56 
60 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                            memo[memo_key] = handle_passed_param( 
     | 
| 
       58 
     | 
    
         
            -
                              declared(passed_children_params, options, declared_children_params)
         
     | 
| 
      
 61 
     | 
    
         
            +
                            memo[memo_key] = handle_passed_param(passed_children_params, params_nested_path_dup) do
         
     | 
| 
      
 62 
     | 
    
         
            +
                              declared(passed_children_params, options, declared_children_params, params_nested_path_dup)
         
     | 
| 
       59 
63 
     | 
    
         
             
                            end
         
     | 
| 
       60 
64 
     | 
    
         
             
                          end
         
     | 
| 
       61 
65 
     | 
    
         
             
                        else
         
     | 
| 
         @@ -75,16 +79,32 @@ module Grape 
     | 
|
| 
       75 
79 
     | 
    
         
             
                      end
         
     | 
| 
       76 
80 
     | 
    
         
             
                    end
         
     | 
| 
       77 
81 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                    def handle_passed_param( 
     | 
| 
       79 
     | 
    
         
            -
                       
     | 
| 
      
 82 
     | 
    
         
            +
                    def handle_passed_param(passed_children_params, params_nested_path, &_block)
         
     | 
| 
      
 83 
     | 
    
         
            +
                      if should_be_empty_hash?(passed_children_params, params_nested_path)
         
     | 
| 
      
 84 
     | 
    
         
            +
                        {}
         
     | 
| 
      
 85 
     | 
    
         
            +
                      elsif should_be_empty_array?(passed_children_params, params_nested_path)
         
     | 
| 
      
 86 
     | 
    
         
            +
                        []
         
     | 
| 
      
 87 
     | 
    
         
            +
                      else
         
     | 
| 
      
 88 
     | 
    
         
            +
                        yield
         
     | 
| 
      
 89 
     | 
    
         
            +
                      end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    def should_be_empty_array?(passed_children_params, params_nested_path)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      passed_children_params.empty? && declared_param_is_array?(params_nested_path)
         
     | 
| 
       80 
94 
     | 
    
         
             
                    end
         
     | 
| 
       81 
95 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                    def  
     | 
| 
       83 
     | 
    
         
            -
                       
     | 
| 
      
 96 
     | 
    
         
            +
                    def declared_param_is_array?(params_nested_path)
         
     | 
| 
      
 97 
     | 
    
         
            +
                      key = route_options_params_key(params_nested_path)
         
     | 
| 
      
 98 
     | 
    
         
            +
                      route_options_params[key] && route_options_params[key][:type] == 'Array'
         
     | 
| 
       84 
99 
     | 
    
         
             
                    end
         
     | 
| 
       85 
100 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                    def  
     | 
| 
       87 
     | 
    
         
            -
                       
     | 
| 
      
 101 
     | 
    
         
            +
                    def should_be_empty_hash?(passed_children_params, params_nested_path)
         
     | 
| 
      
 102 
     | 
    
         
            +
                      passed_children_params.empty? && declared_param_is_hash?(params_nested_path)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    def declared_param_is_hash?(params_nested_path)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      key = route_options_params_key(params_nested_path)
         
     | 
| 
      
 107 
     | 
    
         
            +
                      route_options_params[key] && route_options_params[key][:type] == 'Hash'
         
     | 
| 
       88 
108 
     | 
    
         
             
                    end
         
     | 
| 
       89 
109 
     | 
    
         | 
| 
       90 
110 
     | 
    
         
             
                    def route_options_params
         
     | 
| 
         @@ -95,13 +115,19 @@ module Grape 
     | 
|
| 
       95 
115 
     | 
    
         
             
                      options[:stringify] ? declared_param.to_s : declared_param.to_sym
         
     | 
| 
       96 
116 
     | 
    
         
             
                    end
         
     | 
| 
       97 
117 
     | 
    
         | 
| 
       98 
     | 
    
         
            -
                    def  
     | 
| 
      
 118 
     | 
    
         
            +
                    def route_options_params_key(params_nested_path)
         
     | 
| 
      
 119 
     | 
    
         
            +
                      key = params_nested_path[0]
         
     | 
| 
      
 120 
     | 
    
         
            +
                      key += '[' + params_nested_path[1..-1].join('][') + ']' if params_nested_path.size > 1
         
     | 
| 
      
 121 
     | 
    
         
            +
                      key
         
     | 
| 
      
 122 
     | 
    
         
            +
                    end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                    def optioned_declared_params(**options)
         
     | 
| 
       99 
125 
     | 
    
         
             
                      declared_params = if options[:include_parent_namespaces]
         
     | 
| 
       100 
126 
     | 
    
         
             
                                          # Declared params including parent namespaces
         
     | 
| 
       101 
     | 
    
         
            -
                                          route_setting(: 
     | 
| 
      
 127 
     | 
    
         
            +
                                          route_setting(:declared_params)
         
     | 
| 
       102 
128 
     | 
    
         
             
                                        else
         
     | 
| 
       103 
129 
     | 
    
         
             
                                          # Declared params at current namespace
         
     | 
| 
       104 
     | 
    
         
            -
                                           
     | 
| 
      
 130 
     | 
    
         
            +
                                          namespace_stackable(:declared_params).last || []
         
     | 
| 
       105 
131 
     | 
    
         
             
                                        end
         
     | 
| 
       106 
132 
     | 
    
         | 
| 
       107 
133 
     | 
    
         
             
                      raise ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
         
     | 
| 
         @@ -174,17 +200,17 @@ module Grape 
     | 
|
| 
       174 
200 
     | 
    
         
             
                  def status(status = nil)
         
     | 
| 
       175 
201 
     | 
    
         
             
                    case status
         
     | 
| 
       176 
202 
     | 
    
         
             
                    when Symbol
         
     | 
| 
       177 
     | 
    
         
            -
                      raise ArgumentError, "Status code :#{status} is invalid." unless Rack::Utils::SYMBOL_TO_STATUS_CODE. 
     | 
| 
      
 203 
     | 
    
         
            +
                      raise ArgumentError, "Status code :#{status} is invalid." unless Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(status)
         
     | 
| 
       178 
204 
     | 
    
         
             
                      @status = Rack::Utils.status_code(status)
         
     | 
| 
       179 
205 
     | 
    
         
             
                    when Integer
         
     | 
| 
       180 
206 
     | 
    
         
             
                      @status = status
         
     | 
| 
       181 
207 
     | 
    
         
             
                    when nil
         
     | 
| 
       182 
     | 
    
         
            -
                      return @status if @status
         
     | 
| 
      
 208 
     | 
    
         
            +
                      return @status if instance_variable_defined?(:@status) && @status
         
     | 
| 
       183 
209 
     | 
    
         
             
                      case request.request_method.to_s.upcase
         
     | 
| 
       184 
210 
     | 
    
         
             
                      when Grape::Http::Headers::POST
         
     | 
| 
       185 
211 
     | 
    
         
             
                        201
         
     | 
| 
       186 
212 
     | 
    
         
             
                      when Grape::Http::Headers::DELETE
         
     | 
| 
       187 
     | 
    
         
            -
                        if @body.present?
         
     | 
| 
      
 213 
     | 
    
         
            +
                        if instance_variable_defined?(:@body) && @body.present?
         
     | 
| 
       188 
214 
     | 
    
         
             
                          200
         
     | 
| 
       189 
215 
     | 
    
         
             
                        else
         
     | 
| 
       190 
216 
     | 
    
         
             
                          204
         
     | 
| 
         @@ -235,7 +261,7 @@ module Grape 
     | 
|
| 
       235 
261 
     | 
    
         
             
                      @body = ''
         
     | 
| 
       236 
262 
     | 
    
         
             
                      status 204
         
     | 
| 
       237 
263 
     | 
    
         
             
                    else
         
     | 
| 
       238 
     | 
    
         
            -
                      @body
         
     | 
| 
      
 264 
     | 
    
         
            +
                      instance_variable_defined?(:@body) ? @body : nil
         
     | 
| 
       239 
265 
     | 
    
         
             
                    end
         
     | 
| 
       240 
266 
     | 
    
         
             
                  end
         
     | 
| 
       241 
267 
     | 
    
         | 
| 
         @@ -253,23 +279,36 @@ module Grape 
     | 
|
| 
       253 
279 
     | 
    
         
             
                    body false
         
     | 
| 
       254 
280 
     | 
    
         
             
                  end
         
     | 
| 
       255 
281 
     | 
    
         | 
| 
       256 
     | 
    
         
            -
                  #  
     | 
| 
      
 282 
     | 
    
         
            +
                  # Deprecated method to send files to the client. Use `sendfile` or `stream`
         
     | 
| 
      
 283 
     | 
    
         
            +
                  def file(value = nil)
         
     | 
| 
      
 284 
     | 
    
         
            +
                    if value.is_a?(String)
         
     | 
| 
      
 285 
     | 
    
         
            +
                      warn '[DEPRECATION] Use sendfile or stream to send files.'
         
     | 
| 
      
 286 
     | 
    
         
            +
                      sendfile(value)
         
     | 
| 
      
 287 
     | 
    
         
            +
                    elsif !value.is_a?(NilClass)
         
     | 
| 
      
 288 
     | 
    
         
            +
                      warn '[DEPRECATION] Use stream to use a Stream object.'
         
     | 
| 
      
 289 
     | 
    
         
            +
                      stream(value)
         
     | 
| 
      
 290 
     | 
    
         
            +
                    else
         
     | 
| 
      
 291 
     | 
    
         
            +
                      warn '[DEPRECATION] Use sendfile or stream to send files.'
         
     | 
| 
      
 292 
     | 
    
         
            +
                      sendfile
         
     | 
| 
      
 293 
     | 
    
         
            +
                    end
         
     | 
| 
      
 294 
     | 
    
         
            +
                  end
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
                  # Allows you to send a file to the client via sendfile.
         
     | 
| 
       257 
297 
     | 
    
         
             
                  #
         
     | 
| 
       258 
298 
     | 
    
         
             
                  # @example
         
     | 
| 
       259 
299 
     | 
    
         
             
                  #   get '/file' do
         
     | 
| 
       260 
     | 
    
         
            -
                  #      
     | 
| 
      
 300 
     | 
    
         
            +
                  #     sendfile FileStreamer.new(...)
         
     | 
| 
       261 
301 
     | 
    
         
             
                  #   end
         
     | 
| 
       262 
302 
     | 
    
         
             
                  #
         
     | 
| 
       263 
303 
     | 
    
         
             
                  #   GET /file # => "contents of file"
         
     | 
| 
       264 
     | 
    
         
            -
                  def  
     | 
| 
      
 304 
     | 
    
         
            +
                  def sendfile(value = nil)
         
     | 
| 
       265 
305 
     | 
    
         
             
                    if value.is_a?(String)
         
     | 
| 
       266 
     | 
    
         
            -
                      file_body = Grape:: 
     | 
| 
       267 
     | 
    
         
            -
                      @ 
     | 
| 
      
 306 
     | 
    
         
            +
                      file_body = Grape::ServeStream::FileBody.new(value)
         
     | 
| 
      
 307 
     | 
    
         
            +
                      @stream = Grape::ServeStream::StreamResponse.new(file_body)
         
     | 
| 
       268 
308 
     | 
    
         
             
                    elsif !value.is_a?(NilClass)
         
     | 
| 
       269 
     | 
    
         
            -
                       
     | 
| 
       270 
     | 
    
         
            -
                      @file = Grape::ServeFile::FileResponse.new(value)
         
     | 
| 
      
 309 
     | 
    
         
            +
                      raise ArgumentError, 'Argument must be a file path'
         
     | 
| 
       271 
310 
     | 
    
         
             
                    else
         
     | 
| 
       272 
     | 
    
         
            -
                       
     | 
| 
      
 311 
     | 
    
         
            +
                      stream
         
     | 
| 
       273 
312 
     | 
    
         
             
                    end
         
     | 
| 
       274 
313 
     | 
    
         
             
                  end
         
     | 
| 
       275 
314 
     | 
    
         | 
| 
         @@ -292,7 +331,16 @@ module Grape 
     | 
|
| 
       292 
331 
     | 
    
         
             
                    header 'Content-Length', nil
         
     | 
| 
       293 
332 
     | 
    
         
             
                    header 'Transfer-Encoding', nil
         
     | 
| 
       294 
333 
     | 
    
         
             
                    header 'Cache-Control', 'no-cache' # Skips ETag generation (reading the response up front)
         
     | 
| 
       295 
     | 
    
         
            -
                     
     | 
| 
      
 334 
     | 
    
         
            +
                    if value.is_a?(String)
         
     | 
| 
      
 335 
     | 
    
         
            +
                      file_body = Grape::ServeStream::FileBody.new(value)
         
     | 
| 
      
 336 
     | 
    
         
            +
                      @stream = Grape::ServeStream::StreamResponse.new(file_body)
         
     | 
| 
      
 337 
     | 
    
         
            +
                    elsif value.respond_to?(:each)
         
     | 
| 
      
 338 
     | 
    
         
            +
                      @stream = Grape::ServeStream::StreamResponse.new(value)
         
     | 
| 
      
 339 
     | 
    
         
            +
                    elsif !value.is_a?(NilClass)
         
     | 
| 
      
 340 
     | 
    
         
            +
                      raise ArgumentError, 'Stream object must respond to :each.'
         
     | 
| 
      
 341 
     | 
    
         
            +
                    else
         
     | 
| 
      
 342 
     | 
    
         
            +
                      instance_variable_defined?(:@stream) ? @stream : nil
         
     | 
| 
      
 343 
     | 
    
         
            +
                    end
         
     | 
| 
       296 
344 
     | 
    
         
             
                  end
         
     | 
| 
       297 
345 
     | 
    
         | 
| 
       298 
346 
     | 
    
         
             
                  # Allows you to make use of Grape Entities by setting
         
     | 
| 
         @@ -328,11 +376,12 @@ module Grape 
     | 
|
| 
       328 
376 
     | 
    
         
             
                                     end
         
     | 
| 
       329 
377 
     | 
    
         | 
| 
       330 
378 
     | 
    
         
             
                    representation = { root => representation } if root
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
       331 
380 
     | 
    
         
             
                    if key
         
     | 
| 
       332 
     | 
    
         
            -
                      representation = ( 
     | 
| 
       333 
     | 
    
         
            -
                    elsif entity_class.present? &&  
     | 
| 
      
 381 
     | 
    
         
            +
                      representation = (body || {}).merge(key => representation)
         
     | 
| 
      
 382 
     | 
    
         
            +
                    elsif entity_class.present? && body
         
     | 
| 
       334 
383 
     | 
    
         
             
                      raise ArgumentError, "Representation of type #{representation.class} cannot be merged." unless representation.respond_to?(:merge)
         
     | 
| 
       335 
     | 
    
         
            -
                      representation =  
     | 
| 
      
 384 
     | 
    
         
            +
                      representation = body.merge(representation)
         
     | 
| 
       336 
385 
     | 
    
         
             
                    end
         
     | 
| 
       337 
386 
     | 
    
         | 
| 
       338 
387 
     | 
    
         
             
                    body representation
         
     |