grape 1.1.0 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|