grape 1.1.0 → 1.5.3
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 +278 -44
- data/LICENSE +1 -1
- data/README.md +514 -69
- data/UPGRADING.md +424 -17
- data/grape.gemspec +13 -2
- data/lib/grape.rb +104 -71
- data/lib/grape/api.rb +138 -175
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +283 -0
- data/lib/grape/config.rb +34 -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 +22 -0
- data/lib/grape/dsl/configuration.rb +2 -0
- data/lib/grape/dsl/desc.rb +41 -7
- data/lib/grape/dsl/headers.rb +2 -0
- data/lib/grape/dsl/helpers.rb +5 -2
- data/lib/grape/dsl/inside_route.rb +92 -49
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +9 -0
- data/lib/grape/dsl/parameters.rb +25 -14
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +17 -10
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +24 -4
- data/lib/grape/eager_load.rb +20 -0
- data/lib/grape/endpoint.rb +59 -35
- data/lib/grape/error_formatter.rb +4 -2
- 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 +20 -14
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- 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 +11 -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 +4 -2
- data/lib/grape/exceptions/validation_array_errors.rb +2 -0
- data/lib/grape/exceptions/validation_errors.rb +16 -13
- 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/locale/en.yml +3 -1
- data/lib/grape/middleware/auth/base.rb +7 -7
- 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 +10 -7
- data/lib/grape/middleware/error.rb +21 -16
- 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 +12 -0
- data/lib/grape/middleware/stack.rb +13 -3
- 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 +10 -8
- 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 +4 -2
- data/lib/grape/parser/json.rb +3 -1
- data/lib/grape/parser/xml.rb +3 -1
- data/lib/grape/path.rb +15 -3
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +19 -10
- data/lib/grape/router.rb +30 -29
- data/lib/grape/router/attribute_translator.rb +41 -8
- data/lib/grape/router/pattern.rb +20 -16
- data/lib/grape/router/route.rb +14 -28
- 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 +43 -0
- data/lib/grape/util/cache.rb +20 -0
- data/lib/grape/util/endpoint_configuration.rb +8 -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 +7 -25
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_block.rb +27 -0
- data/lib/grape/util/lazy_object.rb +43 -0
- data/lib/grape/util/lazy_value.rb +98 -0
- data/lib/grape/util/registrable.rb +2 -0
- data/lib/grape/util/reverse_stackable_values.rb +10 -35
- data/lib/grape/util/stackable_values.rb +21 -34
- 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 +16 -6
- data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
- data/lib/grape/validations/params_scope.rb +51 -30
- data/lib/grape/validations/single_attribute_iterator.rb +24 -0
- data/lib/grape/validations/types.rb +13 -38
- 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 +29 -51
- 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/invalid_value.rb +24 -0
- 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 +8 -11
- data/lib/grape/validations/validators/all_or_none.rb +8 -13
- data/lib/grape/validations/validators/allow_blank.rb +3 -1
- data/lib/grape/validations/validators/as.rb +5 -4
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -13
- data/lib/grape/validations/validators/base.rb +20 -16
- data/lib/grape/validations/validators/coerce.rb +46 -29
- data/lib/grape/validations/validators/default.rb +6 -6
- data/lib/grape/validations/validators/exactly_one_of.rb +10 -23
- data/lib/grape/validations/validators/except_values.rb +4 -2
- data/lib/grape/validations/validators/multiple_params_base.rb +17 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -18
- 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 +26 -0
- data/lib/grape/validations/validators/values.rb +18 -6
- 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 +39 -0
- 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 +61 -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 +473 -0
- data/spec/grape/api_spec.rb +565 -12
- data/spec/grape/config_spec.rb +19 -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 +42 -16
- 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 +184 -33
- data/spec/grape/dsl/logger_spec.rb +2 -0
- data/spec/grape/dsl/middleware_spec.rb +10 -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 +12 -0
- data/spec/grape/dsl/settings_spec.rb +2 -0
- data/spec/grape/dsl/validations_spec.rb +2 -0
- data/spec/grape/endpoint/declared_spec.rb +601 -0
- data/spec/grape/endpoint_spec.rb +53 -523
- data/spec/grape/entity_spec.rb +9 -1
- data/spec/grape/exceptions/base_spec.rb +67 -0
- 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 +13 -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 +8 -4
- 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 +25 -7
- 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 +5 -3
- data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
- data/spec/grape/middleware/base_spec.rb +10 -0
- data/spec/grape/middleware/error_spec.rb +3 -1
- data/spec/grape/middleware/exception_spec.rb +4 -2
- data/spec/grape/middleware/formatter_spec.rb +33 -16
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +12 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/header_spec.rb +9 -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 +21 -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 +26 -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 +41 -0
- data/spec/grape/validations/params_scope_spec.rb +213 -9
- data/spec/grape/validations/single_attribute_iterator_spec.rb +58 -0
- 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 +140 -30
- data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +175 -29
- data/spec/grape/validations/validators/coerce_spec.rb +476 -135
- data/spec/grape/validations/validators/default_spec.rb +172 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +204 -38
- data/spec/grape/validations/validators/except_values_spec.rb +4 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +186 -27
- 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 +65 -0
- data/spec/grape/validations/validators/values_spec.rb +30 -5
- data/spec/grape/validations_spec.rb +388 -50
- 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 +22 -20
- data/spec/spec_helper.rb +12 -1
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/chunks.rb +14 -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 +8 -8
- metadata +86 -48
- data/Appraisals +0 -32
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile +0 -35
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_edge.gemfile +0 -35
- 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/pkg/grape-0.17.0.gem +0 -0
- data/pkg/grape-0.19.0.gem +0 -0
@@ -1,18 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/dsl/headers'
|
2
4
|
|
3
5
|
module Grape
|
4
6
|
module Middleware
|
5
7
|
class Base
|
8
|
+
include Helpers
|
9
|
+
|
6
10
|
attr_reader :app, :env, :options
|
7
|
-
|
11
|
+
|
12
|
+
TEXT_HTML = 'text/html'
|
8
13
|
|
9
14
|
include Grape::DSL::Headers
|
10
15
|
|
11
16
|
# @param [Rack Application] app The standard argument for a Rack middleware.
|
12
17
|
# @param [Hash] options A hash of options, simply stored for use by subclasses.
|
13
|
-
def initialize(app,
|
18
|
+
def initialize(app, *options)
|
14
19
|
@app = app
|
15
|
-
@options = default_options.merge(
|
20
|
+
@options = options.any? ? default_options.merge(options.shift) : default_options
|
16
21
|
@app_response = nil
|
17
22
|
end
|
18
23
|
|
@@ -21,7 +26,7 @@ module Grape
|
|
21
26
|
end
|
22
27
|
|
23
28
|
def call(env)
|
24
|
-
dup.call!(env)
|
29
|
+
dup.call!(env).to_a
|
25
30
|
end
|
26
31
|
|
27
32
|
def call!(env)
|
@@ -70,11 +75,9 @@ module Grape
|
|
70
75
|
end
|
71
76
|
|
72
77
|
def mime_types
|
73
|
-
|
74
|
-
content_types.each_pair do |k, v|
|
78
|
+
@mime_type ||= content_types.each_pair.with_object({}) do |(k, v), types_without_params|
|
75
79
|
types_without_params[v.split(';').first] = k
|
76
80
|
end
|
77
|
-
types_without_params
|
78
81
|
end
|
79
82
|
|
80
83
|
private
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/middleware/base'
|
2
4
|
require 'active_support/core_ext/string/output_safety'
|
3
5
|
|
@@ -17,7 +19,7 @@ module Grape
|
|
17
19
|
rescue_subclasses: true, # rescue subclasses of exceptions listed
|
18
20
|
rescue_options: {
|
19
21
|
backtrace: false, # true to display backtrace, true to let Grape handle Grape::Exceptions
|
20
|
-
original_exception: false
|
22
|
+
original_exception: false # true to display exception
|
21
23
|
},
|
22
24
|
rescue_handlers: {}, # rescue handler blocks
|
23
25
|
base_only_rescue_handlers: {}, # rescue handler blocks rescuing only the base class
|
@@ -25,27 +27,26 @@ module Grape
|
|
25
27
|
}
|
26
28
|
end
|
27
29
|
|
28
|
-
def initialize(app,
|
30
|
+
def initialize(app, *options)
|
29
31
|
super
|
30
32
|
self.class.send(:include, @options[:helpers]) if @options[:helpers]
|
31
33
|
end
|
32
34
|
|
33
35
|
def call!(env)
|
34
36
|
@env = env
|
35
|
-
|
36
37
|
begin
|
37
38
|
error_response(catch(:error) do
|
38
39
|
return @app.call(@env)
|
39
40
|
end)
|
40
|
-
rescue Exception =>
|
41
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
41
42
|
handler =
|
42
|
-
rescue_handler_for_base_only_class(
|
43
|
-
rescue_handler_for_class_or_its_ancestor(
|
44
|
-
rescue_handler_for_grape_exception(
|
45
|
-
rescue_handler_for_any_class(
|
43
|
+
rescue_handler_for_base_only_class(e.class) ||
|
44
|
+
rescue_handler_for_class_or_its_ancestor(e.class) ||
|
45
|
+
rescue_handler_for_grape_exception(e.class) ||
|
46
|
+
rescue_handler_for_any_class(e.class) ||
|
46
47
|
raise
|
47
48
|
|
48
|
-
run_rescue_handler(handler,
|
49
|
+
run_rescue_handler(handler, e)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -64,21 +65,19 @@ module Grape
|
|
64
65
|
message = error[:message] || options[:default_message]
|
65
66
|
headers = { Grape::Http::Headers::CONTENT_TYPE => content_type }
|
66
67
|
headers.merge!(error[:headers]) if error[:headers].is_a?(Hash)
|
67
|
-
backtrace = error[:backtrace] || error[:original_exception]
|
68
|
+
backtrace = error[:backtrace] || error[:original_exception]&.backtrace || []
|
68
69
|
original_exception = error.is_a?(Exception) ? error : error[:original_exception] || nil
|
69
70
|
rack_response(format_message(message, backtrace, original_exception), status, headers)
|
70
71
|
end
|
71
72
|
|
72
73
|
def rack_response(message, status = options[:default_status], headers = { Grape::Http::Headers::CONTENT_TYPE => content_type })
|
73
|
-
if headers[Grape::Http::Headers::CONTENT_TYPE] == TEXT_HTML
|
74
|
-
|
75
|
-
end
|
76
|
-
Rack::Response.new([message], status, headers).finish
|
74
|
+
message = ERB::Util.html_escape(message) if headers[Grape::Http::Headers::CONTENT_TYPE] == TEXT_HTML
|
75
|
+
Rack::Response.new([message], status, headers)
|
77
76
|
end
|
78
77
|
|
79
78
|
def format_message(message, backtrace, original_exception = nil)
|
80
79
|
format = env[Grape::Env::API_FORMAT] || options[:format]
|
81
|
-
formatter = Grape::ErrorFormatter.formatter_for(format, options)
|
80
|
+
formatter = Grape::ErrorFormatter.formatter_for(format, **options)
|
82
81
|
throw :error,
|
83
82
|
status: 406,
|
84
83
|
message: "The requested format '#{format}' is not supported.",
|
@@ -127,7 +126,13 @@ module Grape
|
|
127
126
|
handler = public_method(handler)
|
128
127
|
end
|
129
128
|
|
130
|
-
handler.arity.zero? ? instance_exec(&handler) : instance_exec(error, &handler)
|
129
|
+
response = handler.arity.zero? ? instance_exec(&handler) : instance_exec(error, &handler)
|
130
|
+
|
131
|
+
if response.is_a?(Rack::Response)
|
132
|
+
response
|
133
|
+
else
|
134
|
+
run_rescue_handler(:default_rescue_handler, Grape::Exceptions::InvalidResponse.new)
|
135
|
+
end
|
131
136
|
end
|
132
137
|
end
|
133
138
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/middleware/base'
|
2
4
|
|
3
5
|
module Grape
|
4
6
|
module Middleware
|
5
7
|
class Formatter < Base
|
6
|
-
CHUNKED = 'chunked'
|
8
|
+
CHUNKED = 'chunked'
|
7
9
|
|
8
10
|
def default_options
|
9
11
|
{
|
@@ -34,9 +36,9 @@ module Grape
|
|
34
36
|
def build_formatted_response(status, headers, bodies)
|
35
37
|
headers = ensure_content_type(headers)
|
36
38
|
|
37
|
-
if bodies.is_a?(Grape::
|
38
|
-
Grape::
|
39
|
-
resp.body = bodies.
|
39
|
+
if bodies.is_a?(Grape::ServeStream::StreamResponse)
|
40
|
+
Grape::ServeStream::SendfileResponse.new([], status, headers) do |resp|
|
41
|
+
resp.body = bodies.stream
|
40
42
|
end
|
41
43
|
else
|
42
44
|
# Allow content-type to be explicitly overwritten
|
@@ -52,7 +54,7 @@ module Grape
|
|
52
54
|
|
53
55
|
def fetch_formatter(headers, options)
|
54
56
|
api_format = mime_types[headers[Grape::Http::Headers::CONTENT_TYPE]] || env[Grape::Env::API_FORMAT]
|
55
|
-
Grape::Formatter.formatter_for(api_format, options)
|
57
|
+
Grape::Formatter.formatter_for(api_format, **options)
|
56
58
|
end
|
57
59
|
|
58
60
|
# Set the content type header for the API format if it is not already present.
|
@@ -97,7 +99,7 @@ module Grape
|
|
97
99
|
unless content_type_for(fmt)
|
98
100
|
throw :error, status: 415, message: "The provided content-type '#{request.media_type}' is not supported."
|
99
101
|
end
|
100
|
-
parser = Grape::Parser.parser_for fmt, options
|
102
|
+
parser = Grape::Parser.parser_for fmt, **options
|
101
103
|
if parser
|
102
104
|
begin
|
103
105
|
body = (env[Grape::Env::API_REQUEST_BODY] = parser.call(body, env))
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Grape
|
2
4
|
module Middleware
|
3
5
|
# Class to handle the stack of middlewares based on ActionDispatch::MiddlewareStack
|
@@ -28,6 +30,10 @@ module Grape
|
|
28
30
|
def inspect
|
29
31
|
klass.to_s
|
30
32
|
end
|
33
|
+
|
34
|
+
def use_in(builder)
|
35
|
+
builder.use(@klass, *@args, &@block)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
include Enumerable
|
@@ -60,6 +66,7 @@ module Grape
|
|
60
66
|
middleware = self.class::Middleware.new(*args, &block)
|
61
67
|
middlewares.insert(index, middleware)
|
62
68
|
end
|
69
|
+
ruby2_keywords :insert if respond_to?(:ruby2_keywords, true)
|
63
70
|
|
64
71
|
alias insert_before insert
|
65
72
|
|
@@ -67,16 +74,19 @@ module Grape
|
|
67
74
|
index = assert_index(index, :after)
|
68
75
|
insert(index + 1, *args, &block)
|
69
76
|
end
|
77
|
+
ruby2_keywords :insert_after if respond_to?(:ruby2_keywords, true)
|
70
78
|
|
71
79
|
def use(*args, &block)
|
72
80
|
middleware = self.class::Middleware.new(*args, &block)
|
73
81
|
middlewares.push(middleware)
|
74
82
|
end
|
83
|
+
ruby2_keywords :use if respond_to?(:ruby2_keywords, true)
|
75
84
|
|
76
85
|
def merge_with(middleware_specs)
|
77
86
|
middleware_specs.each do |operation, *args|
|
78
87
|
if args.last.is_a?(Proc)
|
79
|
-
|
88
|
+
last_proc = args.pop
|
89
|
+
public_send(operation, *args, &last_proc)
|
80
90
|
else
|
81
91
|
public_send(operation, *args)
|
82
92
|
end
|
@@ -87,7 +97,7 @@ module Grape
|
|
87
97
|
def build(builder = Rack::Builder.new)
|
88
98
|
others.shift(others.size).each(&method(:merge_with))
|
89
99
|
middlewares.each do |m|
|
90
|
-
m.
|
100
|
+
m.use_in(builder)
|
91
101
|
end
|
92
102
|
builder
|
93
103
|
end
|
@@ -96,7 +106,7 @@ module Grape
|
|
96
106
|
# @param [Array] other_specs An array of middleware specifications (e.g. [[:use, klass], [:insert_before, *args]])
|
97
107
|
def concat(other_specs)
|
98
108
|
@others << Array(other_specs).reject { |o| o.first == :use }
|
99
|
-
merge_with
|
109
|
+
merge_with(Array(other_specs).select { |o| o.first == :use })
|
100
110
|
end
|
101
111
|
|
102
112
|
protected
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/middleware/base'
|
2
4
|
require 'grape/middleware/versioner/parse_media_type_patch'
|
3
5
|
|
@@ -24,10 +26,10 @@ module Grape
|
|
24
26
|
# route.
|
25
27
|
class Header < Base
|
26
28
|
VENDOR_VERSION_HEADER_REGEX =
|
27
|
-
/\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))?(?:\+([a-z0-9*\-.]+))?\z
|
29
|
+
/\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))?(?:\+([a-z0-9*\-.]+))?\z/.freeze
|
28
30
|
|
29
|
-
HAS_VENDOR_REGEX = /\Avnd\.[a-z0-9.\-_!#\$&\^]
|
30
|
-
HAS_VERSION_REGEX = /\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))
|
31
|
+
HAS_VENDOR_REGEX = /\Avnd\.[a-z0-9.\-_!#\$&\^]+/.freeze
|
32
|
+
HAS_VERSION_REGEX = /\Avnd\.([a-z0-9.\-_!#\$&\^]+?)(?:-([a-z0-9*.]+))+/.freeze
|
31
33
|
|
32
34
|
def before
|
33
35
|
strict_header_checks if strict?
|
@@ -61,7 +63,7 @@ module Grape
|
|
61
63
|
|
62
64
|
def an_accept_header_with_version_and_vendor_is_present?
|
63
65
|
header.qvalues.keys.any? do |h|
|
64
|
-
VENDOR_VERSION_HEADER_REGEX
|
66
|
+
VENDOR_VERSION_HEADER_REGEX.match?(h.sub('application/', ''))
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
@@ -99,7 +101,7 @@ module Grape
|
|
99
101
|
def available_media_types
|
100
102
|
available_media_types = []
|
101
103
|
|
102
|
-
content_types.
|
104
|
+
content_types.each_key do |extension|
|
103
105
|
versions.reverse_each do |version|
|
104
106
|
available_media_types += [
|
105
107
|
"application/vnd.#{vendor}-#{version}+#{extension}",
|
@@ -111,7 +113,7 @@ module Grape
|
|
111
113
|
|
112
114
|
available_media_types << "application/vnd.#{vendor}"
|
113
115
|
|
114
|
-
content_types.
|
116
|
+
content_types.each_value do |media_type|
|
115
117
|
available_media_types << media_type
|
116
118
|
end
|
117
119
|
|
@@ -173,7 +175,7 @@ module Grape
|
|
173
175
|
# @return [Boolean] whether the content type sets a vendor
|
174
176
|
def vendor?(media_type)
|
175
177
|
_, subtype = Rack::Accept::Header.parse_media_type(media_type)
|
176
|
-
subtype[HAS_VENDOR_REGEX]
|
178
|
+
subtype.present? && subtype[HAS_VENDOR_REGEX]
|
177
179
|
end
|
178
180
|
|
179
181
|
def request_vendor(media_type)
|
@@ -190,7 +192,7 @@ module Grape
|
|
190
192
|
# @return [Boolean] whether the content type sets an API version
|
191
193
|
def version?(media_type)
|
192
194
|
_, subtype = Rack::Accept::Header.parse_media_type(media_type)
|
193
|
-
subtype[HAS_VERSION_REGEX]
|
195
|
+
subtype.present? && subtype[HAS_VERSION_REGEX]
|
194
196
|
end
|
195
197
|
end
|
196
198
|
end
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
module Accept
|
3
5
|
module Header
|
6
|
+
ALLOWED_CHARACTERS = %r{^([a-z*]+)\/([a-z0-9*\&\^\-_#\$!.+]+)(?:;([a-z0-9=;]+))?$}.freeze
|
4
7
|
class << self
|
5
8
|
# Corrected version of https://github.com/mjackson/rack-accept/blob/master/lib/rack/accept/header.rb#L40-L44
|
6
9
|
def parse_media_type(media_type)
|
7
10
|
# see http://tools.ietf.org/html/rfc6838#section-4.2 for allowed characters in media type names
|
8
|
-
m = media_type
|
11
|
+
m = media_type&.match(ALLOWED_CHARACTERS)
|
9
12
|
m ? [m[1], m[2], m[3] || ''] : []
|
10
13
|
end
|
11
14
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'grape/middleware/base'
|
2
4
|
|
3
5
|
module Grape
|
@@ -34,7 +36,7 @@ module Grape
|
|
34
36
|
|
35
37
|
pieces = path.split('/')
|
36
38
|
potential_version = pieces[1]
|
37
|
-
return unless potential_version
|
39
|
+
return unless potential_version&.match?(options[:pattern])
|
38
40
|
throw :error, status: 404, message: '404 API Version Not Found' if options[:versions] && !options[:versions].find { |v| v.to_s == potential_version }
|
39
41
|
env[Grape::Env::API_VERSION] = potential_version
|
40
42
|
end
|
data/lib/grape/namespace.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'grape/util/cache'
|
4
|
+
|
1
5
|
module Grape
|
2
6
|
# A container for endpoints or other namespaces, which allows for both
|
3
7
|
# logical grouping of endpoints as well as sharing common configuration.
|
@@ -23,13 +27,21 @@ module Grape
|
|
23
27
|
|
24
28
|
# (see ::joined_space_path)
|
25
29
|
def self.joined_space(settings)
|
26
|
-
|
30
|
+
settings&.map(&:space)
|
27
31
|
end
|
28
32
|
|
29
33
|
# Join the namespaces from a list of settings to create a path prefix.
|
30
34
|
# @param settings [Array] list of Grape::Util::InheritableSettings.
|
31
35
|
def self.joined_space_path(settings)
|
32
|
-
Grape::Router.normalize_path(joined_space(settings))
|
36
|
+
Grape::Router.normalize_path(JoinedSpaceCache[joined_space(settings)])
|
37
|
+
end
|
38
|
+
|
39
|
+
class JoinedSpaceCache < Grape::Util::Cache
|
40
|
+
def initialize
|
41
|
+
@cache = Hash.new do |h, joined_space|
|
42
|
+
h[joined_space] = -joined_space.join('/')
|
43
|
+
end
|
44
|
+
end
|
33
45
|
end
|
34
46
|
end
|
35
47
|
end
|