grape 2.4.0 → 4.0.1
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 +351 -0
- data/CONTRIBUTING.md +18 -10
- data/README.md +457 -228
- data/UPGRADING.md +1240 -1
- data/grape.gemspec +7 -7
- data/lib/grape/api/instance.rb +65 -116
- data/lib/grape/api.rb +53 -62
- data/lib/grape/content_types.rb +58 -3
- data/lib/grape/cookies.rb +2 -6
- data/lib/grape/declared_params_handler.rb +116 -0
- data/lib/grape/dry_types.rb +48 -4
- data/lib/grape/dsl/callbacks.rb +8 -58
- data/lib/grape/dsl/declared.rb +35 -0
- data/lib/grape/dsl/desc.rb +24 -67
- data/lib/grape/dsl/entity.rb +106 -0
- data/lib/grape/dsl/helpers.rb +80 -65
- data/lib/grape/dsl/inside_route.rb +56 -296
- data/lib/grape/dsl/logger.rb +4 -9
- data/lib/grape/dsl/middleware.rb +22 -40
- data/lib/grape/dsl/parameters.rb +86 -93
- data/lib/grape/dsl/request_response.rb +139 -139
- data/lib/grape/dsl/rescue_options.rb +25 -0
- data/lib/grape/dsl/routing.rb +328 -203
- data/lib/grape/dsl/settings.rb +29 -135
- data/lib/grape/dsl/validations.rb +38 -44
- data/lib/grape/dsl/version_options.rb +23 -0
- data/lib/grape/endpoint/options.rb +25 -0
- data/lib/grape/endpoint.rb +285 -245
- data/lib/grape/env.rb +8 -3
- data/lib/grape/error_formatter/base.rb +27 -21
- data/lib/grape/error_formatter/json.rb +6 -0
- data/lib/grape/error_formatter/txt.rb +10 -10
- data/lib/grape/error_formatter.rb +6 -2
- data/lib/grape/exceptions/base.rb +20 -44
- data/lib/grape/exceptions/error_response.rb +48 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/internal_server_error.rb +16 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_message_body.rb +1 -1
- data/lib/grape/exceptions/invalid_version_header.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/method_not_allowed.rb +1 -1
- data/lib/grape/exceptions/missing_group_type.rb +0 -2
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/request_error.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +1 -1
- data/lib/grape/exceptions/unknown_error_formatter.rb +11 -0
- data/lib/grape/exceptions/unknown_parameter.rb +1 -1
- data/lib/grape/exceptions/unknown_params_builder.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
- data/lib/grape/exceptions/validation.rb +25 -7
- data/lib/grape/exceptions/validation_array_errors.rb +4 -0
- data/lib/grape/exceptions/validation_errors.rb +21 -23
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +6 -9
- data/lib/grape/json.rb +38 -2
- data/lib/grape/locale/en.yml +3 -5
- data/lib/grape/middleware/auth/base.rb +4 -3
- data/lib/grape/middleware/auth/dsl.rb +9 -23
- data/lib/grape/middleware/base.rb +41 -36
- data/lib/grape/middleware/error.rb +271 -73
- data/lib/grape/middleware/formatter.rb +152 -63
- data/lib/grape/middleware/precomputed_content_types.rb +51 -0
- data/lib/grape/middleware/stack.rb +20 -11
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -3
- data/lib/grape/middleware/versioner/base.rb +40 -48
- data/lib/grape/middleware/versioner/header.rb +5 -23
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +54 -7
- data/lib/grape/mountable.rb +22 -0
- data/lib/grape/namespace.rb +19 -11
- data/lib/grape/params_builder/base.rb +2 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +1 -1
- data/lib/grape/params_builder.rb +2 -19
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/path.rb +8 -72
- data/lib/grape/precompiled_json.rb +50 -0
- data/lib/grape/request.rb +57 -20
- data/lib/grape/router/base_route.rb +53 -7
- data/lib/grape/router/greedy_route.rb +16 -6
- data/lib/grape/router/mustermann_pattern.rb +44 -0
- data/lib/grape/router/pattern/path.rb +78 -0
- data/lib/grape/router/pattern.rb +65 -37
- data/lib/grape/router/route.rb +66 -18
- data/lib/grape/router.rb +126 -115
- data/lib/grape/serve_stream/file_body.rb +7 -0
- data/lib/grape/serve_stream/sendfile_response.rb +3 -5
- data/lib/grape/serve_stream/stream_response.rb +7 -0
- data/lib/grape/testing.rb +33 -0
- data/lib/grape/util/api_description.rb +67 -0
- data/lib/grape/util/cache.rb +22 -2
- data/lib/grape/util/deep_freeze.rb +34 -0
- data/lib/grape/util/freeze_on_new.rb +20 -0
- data/lib/grape/util/inheritable_setting.rb +777 -39
- data/lib/grape/util/lazy/base.rb +16 -0
- data/lib/grape/util/lazy/block.rb +2 -9
- data/lib/grape/util/lazy/value.rb +2 -9
- data/lib/grape/util/lazy/value_enumerable.rb +13 -16
- data/lib/grape/util/media_type.rb +13 -9
- data/lib/grape/util/path_normalizer.rb +37 -0
- data/lib/grape/util/registry.rb +13 -3
- data/lib/grape/util/shadowed_rescue_handlers.rb +49 -0
- data/lib/grape/util/stackable_values.rb +39 -10
- data/lib/grape/util/translation.rb +42 -0
- data/lib/grape/validations/attributes_iterator.rb +61 -29
- data/lib/grape/validations/coerce_options.rb +21 -0
- data/lib/grape/validations/contract_scope.rb +8 -13
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/oneof_collector.rb +35 -0
- data/lib/grape/validations/param_scope_tracker.rb +62 -0
- data/lib/grape/validations/params_documentation.rb +52 -0
- data/lib/grape/validations/params_scope.rb +217 -304
- data/lib/grape/validations/shared_options.rb +19 -0
- data/lib/grape/validations/single_attribute_iterator.rb +6 -4
- data/lib/grape/validations/types/array_coercer.rb +7 -10
- data/lib/grape/validations/types/custom_type_coercer.rb +47 -85
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +1 -1
- data/lib/grape/validations/types/dry_type_coercer.rb +10 -15
- data/lib/grape/validations/types/json.rb +1 -3
- data/lib/grape/validations/types/multiple_type_coercer.rb +5 -3
- data/lib/grape/validations/types/primitive_coercer.rb +14 -33
- data/lib/grape/validations/types/set_coercer.rb +1 -1
- data/lib/grape/validations/types/variant_collection_coercer.rb +16 -3
- data/lib/grape/validations/types.rb +29 -51
- data/lib/grape/validations/validations_spec.rb +164 -0
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +6 -3
- data/lib/grape/validations/validators/allow_blank_validator.rb +10 -5
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +5 -2
- data/lib/grape/validations/validators/base.rb +118 -34
- data/lib/grape/validations/validators/coerce_validator.rb +25 -37
- data/lib/grape/validations/validators/contract_scope_validator.rb +10 -5
- data/lib/grape/validations/validators/default_validator.rb +13 -20
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +10 -3
- data/lib/grape/validations/validators/except_values_validator.rb +14 -4
- data/lib/grape/validations/validators/length_validator.rb +23 -22
- data/lib/grape/validations/validators/multiple_params_base.rb +12 -9
- data/lib/grape/validations/validators/{mutual_exclusion_validator.rb → mutually_exclusive_validator.rb} +4 -2
- data/lib/grape/validations/validators/oneof_validator.rb +51 -0
- data/lib/grape/validations/validators/presence_validator.rb +4 -2
- data/lib/grape/validations/validators/regexp_validator.rb +11 -3
- data/lib/grape/validations/validators/same_as_validator.rb +7 -15
- data/lib/grape/validations/validators/values_validator.rb +34 -26
- data/lib/grape/version.rb +1 -2
- data/lib/grape/xml.rb +8 -1
- data/lib/grape.rb +58 -31
- metadata +62 -39
- data/lib/grape/api/helpers.rb +0 -9
- data/lib/grape/dsl/api.rb +0 -17
- data/lib/grape/dsl/configuration.rb +0 -15
- data/lib/grape/exceptions/conflicting_types.rb +0 -11
- data/lib/grape/exceptions/empty_message_body.rb +0 -11
- data/lib/grape/exceptions/invalid_parameters.rb +0 -11
- data/lib/grape/exceptions/missing_option.rb +0 -11
- data/lib/grape/exceptions/too_deep_parameters.rb +0 -11
- data/lib/grape/exceptions/too_many_multipart_files.rb +0 -11
- data/lib/grape/exceptions/unknown_options.rb +0 -11
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +0 -24
- data/lib/grape/extensions/hash.rb +0 -27
- data/lib/grape/extensions/hashie/mash.rb +0 -24
- data/lib/grape/middleware/globals.rb +0 -14
- data/lib/grape/types/invalid_value.rb +0 -8
- data/lib/grape/util/base_inheritable.rb +0 -43
- data/lib/grape/util/inheritable_values.rb +0 -29
- data/lib/grape/util/reverse_stackable_values.rb +0 -15
- data/lib/grape/util/strict_hash_configuration.rb +0 -108
- data/lib/grape/validations/attributes_doc.rb +0 -60
- data/lib/grape/validations/validator_factory.rb +0 -15
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module Validations
|
|
5
|
+
# Holds per-request mutable state that must not live on shared ParamsScope
|
|
6
|
+
# instances. Both trackers are identity-keyed hashes so that ParamsScope
|
|
7
|
+
# objects can serve as keys without relying on value equality.
|
|
8
|
+
#
|
|
9
|
+
# Lifecycle is managed by Endpoint#run_validators via +.track+.
|
|
10
|
+
# Use +.current+ to access the instance for the running request.
|
|
11
|
+
class ParamScopeTracker
|
|
12
|
+
# Fiber-local key used to store the current tracker.
|
|
13
|
+
# Fiber[] (Ruby 3.0+) is used instead of Thread.current[] so that
|
|
14
|
+
# fiber-based servers (e.g. Falcon with async) isolate each request's
|
|
15
|
+
# tracker within its own fiber rather than sharing state across all
|
|
16
|
+
# fibers running on the same thread.
|
|
17
|
+
FIBER_KEY = :grape_param_scope_tracker
|
|
18
|
+
EMPTY_PARAMS = [].freeze
|
|
19
|
+
|
|
20
|
+
def self.track
|
|
21
|
+
previous = Fiber[FIBER_KEY]
|
|
22
|
+
Fiber[FIBER_KEY] = new
|
|
23
|
+
yield
|
|
24
|
+
ensure
|
|
25
|
+
Fiber[FIBER_KEY] = previous
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.current
|
|
29
|
+
Fiber[FIBER_KEY]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def store_index(scope, index)
|
|
33
|
+
index_tracker.store(scope, index)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def index_for(scope)
|
|
37
|
+
index_tracker[scope]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns qualifying params for +scope+, or EMPTY_PARAMS if none were stored.
|
|
41
|
+
# Note: an explicitly stored empty array and "never stored" are treated identically
|
|
42
|
+
# by callers (both yield a blank result that falls through to the parent params).
|
|
43
|
+
def qualifying_params(scope)
|
|
44
|
+
qualifying_params_tracker.fetch(scope, EMPTY_PARAMS)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def store_qualifying_params(scope, params)
|
|
48
|
+
qualifying_params_tracker.store(scope, params)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def index_tracker
|
|
54
|
+
@index_tracker ||= {}.compare_by_identity
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def qualifying_params_tracker
|
|
58
|
+
@qualifying_params_tracker ||= {}.compare_by_identity
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Grape
|
|
4
|
+
module Validations
|
|
5
|
+
# Documents parameters of an endpoint. Reads from a frozen
|
|
6
|
+
# +ValidationsSpec+; never mutates the user's validations hash.
|
|
7
|
+
module ParamsDocumentation
|
|
8
|
+
def document_params(attrs, spec)
|
|
9
|
+
return if @api.inheritable_setting.do_not_document?
|
|
10
|
+
|
|
11
|
+
documented_attrs = attrs.to_h do |name|
|
|
12
|
+
[full_name(name), extract_details(spec)]
|
|
13
|
+
end
|
|
14
|
+
@api.inheritable_setting.add_params_documentation(documented_attrs)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def extract_details(spec)
|
|
20
|
+
details = {}
|
|
21
|
+
details[:required] = spec.required?
|
|
22
|
+
details[:type] = TypeCache[spec.coerce_type] if spec.coerce_type
|
|
23
|
+
details[:values] = spec.values if spec.values
|
|
24
|
+
details[:except_values] = spec.except_values if spec.except_values
|
|
25
|
+
details[:default] = spec.default unless spec.default.nil?
|
|
26
|
+
|
|
27
|
+
length = spec.raw[:length]
|
|
28
|
+
if length.is_a?(Hash)
|
|
29
|
+
details[:min_length] = length[:min] if length.key?(:min)
|
|
30
|
+
details[:max_length] = length[:max] if length.key?(:max)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc = spec.raw[:desc] || spec.raw[:description]
|
|
34
|
+
details[:desc] = desc if desc
|
|
35
|
+
|
|
36
|
+
documentation = spec.raw[:documentation]
|
|
37
|
+
details[:documentation] = documentation if documentation
|
|
38
|
+
|
|
39
|
+
details
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class TypeCache < Grape::Util::Cache
|
|
43
|
+
def initialize
|
|
44
|
+
super
|
|
45
|
+
@cache = Hash.new do |h, type|
|
|
46
|
+
h[type] = type.to_s
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|