grape 2.2.0 → 2.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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +41 -18
  5. data/UPGRADING.md +75 -1
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +25 -60
  8. data/lib/grape/api.rb +44 -76
  9. data/lib/grape/cookies.rb +31 -25
  10. data/lib/grape/dsl/api.rb +0 -2
  11. data/lib/grape/dsl/desc.rb +27 -24
  12. data/lib/grape/dsl/headers.rb +1 -1
  13. data/lib/grape/dsl/helpers.rb +1 -1
  14. data/lib/grape/dsl/inside_route.rb +17 -40
  15. data/lib/grape/dsl/parameters.rb +5 -5
  16. data/lib/grape/dsl/routing.rb +14 -13
  17. data/lib/grape/endpoint.rb +100 -106
  18. data/lib/grape/error_formatter/base.rb +51 -21
  19. data/lib/grape/error_formatter/json.rb +7 -24
  20. data/lib/grape/error_formatter/serializable_hash.rb +7 -0
  21. data/lib/grape/error_formatter/txt.rb +13 -20
  22. data/lib/grape/error_formatter/xml.rb +3 -13
  23. data/lib/grape/error_formatter.rb +4 -12
  24. data/lib/grape/exceptions/base.rb +18 -30
  25. data/lib/grape/exceptions/conflicting_types.rb +11 -0
  26. data/lib/grape/exceptions/invalid_parameters.rb +11 -0
  27. data/lib/grape/exceptions/too_deep_parameters.rb +11 -0
  28. data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
  29. data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
  30. data/lib/grape/exceptions/validation.rb +5 -4
  31. data/lib/grape/exceptions/validation_errors.rb +2 -2
  32. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +2 -5
  33. data/lib/grape/extensions/hash.rb +2 -1
  34. data/lib/grape/extensions/hashie/mash.rb +3 -5
  35. data/lib/grape/formatter/base.rb +16 -0
  36. data/lib/grape/formatter/json.rb +4 -6
  37. data/lib/grape/formatter/serializable_hash.rb +1 -1
  38. data/lib/grape/formatter/txt.rb +3 -5
  39. data/lib/grape/formatter/xml.rb +4 -6
  40. data/lib/grape/formatter.rb +4 -12
  41. data/lib/grape/locale/en.yml +44 -44
  42. data/lib/grape/middleware/auth/base.rb +11 -32
  43. data/lib/grape/middleware/auth/dsl.rb +23 -29
  44. data/lib/grape/middleware/base.rb +30 -11
  45. data/lib/grape/middleware/error.rb +18 -24
  46. data/lib/grape/middleware/formatter.rb +39 -73
  47. data/lib/grape/middleware/stack.rb +26 -36
  48. data/lib/grape/middleware/versioner/accept_version_header.rb +1 -3
  49. data/lib/grape/middleware/versioner/base.rb +74 -0
  50. data/lib/grape/middleware/versioner/header.rb +4 -10
  51. data/lib/grape/middleware/versioner/param.rb +2 -5
  52. data/lib/grape/middleware/versioner/path.rb +0 -2
  53. data/lib/grape/middleware/versioner.rb +5 -3
  54. data/lib/grape/namespace.rb +1 -1
  55. data/lib/grape/params_builder/base.rb +18 -0
  56. data/lib/grape/params_builder/hash.rb +11 -0
  57. data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
  58. data/lib/grape/params_builder/hashie_mash.rb +11 -0
  59. data/lib/grape/params_builder.rb +32 -0
  60. data/lib/grape/parser/base.rb +16 -0
  61. data/lib/grape/parser/json.rb +6 -8
  62. data/lib/grape/parser/xml.rb +6 -8
  63. data/lib/grape/parser.rb +5 -7
  64. data/lib/grape/path.rb +39 -56
  65. data/lib/grape/request.rb +162 -23
  66. data/lib/grape/router/base_route.rb +2 -2
  67. data/lib/grape/router/greedy_route.rb +2 -2
  68. data/lib/grape/router/pattern.rb +23 -18
  69. data/lib/grape/router/route.rb +14 -6
  70. data/lib/grape/router.rb +30 -12
  71. data/lib/grape/util/registry.rb +27 -0
  72. data/lib/grape/validations/contract_scope.rb +2 -39
  73. data/lib/grape/validations/params_scope.rb +15 -14
  74. data/lib/grape/validations/types/dry_type_coercer.rb +10 -6
  75. data/lib/grape/validations/validator_factory.rb +2 -2
  76. data/lib/grape/validations/validators/allow_blank_validator.rb +1 -1
  77. data/lib/grape/validations/validators/base.rb +7 -11
  78. data/lib/grape/validations/validators/coerce_validator.rb +1 -1
  79. data/lib/grape/validations/validators/contract_scope_validator.rb +41 -0
  80. data/lib/grape/validations/validators/default_validator.rb +1 -1
  81. data/lib/grape/validations/validators/except_values_validator.rb +2 -2
  82. data/lib/grape/validations/validators/length_validator.rb +1 -1
  83. data/lib/grape/validations/validators/presence_validator.rb +1 -1
  84. data/lib/grape/validations/validators/regexp_validator.rb +2 -2
  85. data/lib/grape/validations/validators/values_validator.rb +15 -57
  86. data/lib/grape/validations.rb +8 -17
  87. data/lib/grape/version.rb +1 -1
  88. data/lib/grape.rb +14 -2
  89. metadata +24 -16
  90. data/lib/grape/http/headers.rb +0 -55
  91. data/lib/grape/middleware/helpers.rb +0 -12
  92. data/lib/grape/middleware/versioner_helpers.rb +0 -75
  93. data/lib/grape/util/lazy/object.rb +0 -45
  94. data/lib/grape/validations/types/build_coercer.rb +0 -92
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Http
5
- module Headers
6
- HTTP_ACCEPT_VERSION = 'HTTP_ACCEPT_VERSION'
7
- HTTP_ACCEPT = 'HTTP_ACCEPT'
8
- HTTP_TRANSFER_ENCODING = 'HTTP_TRANSFER_ENCODING'
9
-
10
- ALLOW = 'Allow'
11
- LOCATION = 'Location'
12
- X_CASCADE = 'X-Cascade'
13
- TRANSFER_ENCODING = 'Transfer-Encoding'
14
-
15
- SUPPORTED_METHODS = [
16
- Rack::GET,
17
- Rack::POST,
18
- Rack::PUT,
19
- Rack::PATCH,
20
- Rack::DELETE,
21
- Rack::HEAD,
22
- Rack::OPTIONS
23
- ].freeze
24
-
25
- SUPPORTED_METHODS_WITHOUT_OPTIONS = (SUPPORTED_METHODS - [Rack::OPTIONS]).freeze
26
-
27
- HTTP_HEADERS = Grape::Util::Lazy::Object.new do
28
- common_http_headers = %w[
29
- Version
30
- Host
31
- Connection
32
- Cache-Control
33
- Dnt
34
- Upgrade-Insecure-Requests
35
- User-Agent
36
- Sec-Fetch-Dest
37
- Accept
38
- Sec-Fetch-Site
39
- Sec-Fetch-Mode
40
- Sec-Fetch-User
41
- Accept-Encoding
42
- Accept-Language
43
- Cookie
44
- ].freeze
45
- common_http_headers.each_with_object({}) do |header, response|
46
- response["HTTP_#{header.upcase.tr('-', '_')}"] = header
47
- end.freeze
48
- end
49
-
50
- def self.find_supported_method(route_method)
51
- Grape::Http::Headers::SUPPORTED_METHODS.detect { |supported_method| supported_method.casecmp(route_method).zero? }
52
- end
53
- end
54
- end
55
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Middleware
5
- # Common methods for all types of Grape middleware
6
- module Helpers
7
- def context
8
- env[Grape::Env::API_ENDPOINT]
9
- end
10
- end
11
- end
12
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Middleware
5
- module VersionerHelpers
6
- DEFAULT_PATTERN = /.*/i.freeze
7
- DEFAULT_PARAMETER = 'apiver'
8
-
9
- def default_options
10
- {
11
- versions: nil,
12
- prefix: nil,
13
- mount_path: nil,
14
- pattern: DEFAULT_PATTERN,
15
- version_options: {
16
- strict: false,
17
- cascade: true,
18
- parameter: DEFAULT_PARAMETER
19
- }
20
- }
21
- end
22
-
23
- def versions
24
- options[:versions]
25
- end
26
-
27
- def prefix
28
- options[:prefix]
29
- end
30
-
31
- def mount_path
32
- options[:mount_path]
33
- end
34
-
35
- def pattern
36
- options[:pattern]
37
- end
38
-
39
- def version_options
40
- options[:version_options]
41
- end
42
-
43
- def strict?
44
- version_options[:strict]
45
- end
46
-
47
- # By default those errors contain an `X-Cascade` header set to `pass`, which allows nesting and stacking
48
- # of routes (see Grape::Router) for more information). To prevent
49
- # this behavior, and not add the `X-Cascade` header, one can set the `:cascade` option to `false`.
50
- def cascade?
51
- version_options[:cascade]
52
- end
53
-
54
- def parameter_key
55
- version_options[:parameter]
56
- end
57
-
58
- def vendor
59
- version_options[:vendor]
60
- end
61
-
62
- def error_headers
63
- cascade? ? { Grape::Http::Headers::X_CASCADE => 'pass' } : {}
64
- end
65
-
66
- def potential_version_match?(potential_version)
67
- versions.blank? || versions.any? { |v| v.to_s == potential_version }
68
- end
69
-
70
- def version_not_found!
71
- throw :error, status: 404, message: '404 API Version Not Found', headers: { Grape::Http::Headers::X_CASCADE => 'pass' }
72
- end
73
- end
74
- end
75
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Based on https://github.com/HornsAndHooves/lazy_object
4
-
5
- module Grape
6
- module Util
7
- module Lazy
8
- class Object < BasicObject
9
- attr_reader :callable
10
-
11
- def initialize(&callable)
12
- @callable = callable
13
- end
14
-
15
- def __target_object__
16
- @__target_object__ ||= callable.call
17
- end
18
-
19
- def ==(other)
20
- __target_object__ == other
21
- end
22
-
23
- def !=(other)
24
- __target_object__ != other
25
- end
26
-
27
- def !
28
- !__target_object__
29
- end
30
-
31
- def method_missing(method_name, *args, &block)
32
- if __target_object__.respond_to?(method_name)
33
- __target_object__.send(method_name, *args, &block)
34
- else
35
- super
36
- end
37
- end
38
-
39
- def respond_to_missing?(method_name, include_priv = false)
40
- __target_object__.respond_to?(method_name, include_priv)
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module Validations
5
- module Types
6
- module BuildCoercer
7
- # Chooses the best coercer for the given type. For example, if the type
8
- # is Integer, it will return a coercer which will be able to coerce a value
9
- # to the integer.
10
- #
11
- # There are a few very special coercers which might be returned.
12
- #
13
- # +Grape::Types::MultipleTypeCoercer+ is a coercer which is returned when
14
- # the given type implies values in an array with different types.
15
- # For example, +[Integer, String]+ allows integer and string values in
16
- # an array.
17
- #
18
- # +Grape::Types::CustomTypeCoercer+ is a coercer which is returned when
19
- # a method is specified by a user with +coerce_with+ option or the user
20
- # specifies a custom type which implements requirments of
21
- # +Grape::Types::CustomTypeCoercer+.
22
- #
23
- # +Grape::Types::CustomTypeCollectionCoercer+ is a very similar to the
24
- # previous one, but it expects an array or set of values having a custom
25
- # type implemented by the user.
26
- #
27
- # There is also a group of custom types implemented by Grape, check
28
- # +Grape::Validations::Types::SPECIAL+ to get the full list.
29
- #
30
- # @param type [Class] the type to which input strings
31
- # should be coerced
32
- # @param method [Class,#call] the coercion method to use
33
- # @return [Object] object to be used
34
- # for coercion and type validation
35
- def self.build_coercer(type, method: nil, strict: false)
36
- cache_instance(type, method, strict) do
37
- create_coercer_instance(type, method, strict)
38
- end
39
- end
40
-
41
- def self.create_coercer_instance(type, method, strict)
42
- # Maps a custom type provided by Grape, it doesn't map types wrapped by collections!!!
43
- type = Types.map_special(type)
44
-
45
- # Use a special coercer for multiply-typed parameters.
46
- if Types.multiple?(type)
47
- MultipleTypeCoercer.new(type, method)
48
-
49
- # Use a special coercer for custom types and coercion methods.
50
- elsif method || Types.custom?(type)
51
- CustomTypeCoercer.new(type, method)
52
-
53
- # Special coercer for collections of types that implement a parse method.
54
- # CustomTypeCoercer (above) already handles such types when an explicit coercion
55
- # method is supplied.
56
- elsif Types.collection_of_custom?(type)
57
- Types::CustomTypeCollectionCoercer.new(
58
- Types.map_special(type.first), type.is_a?(Set)
59
- )
60
- else
61
- DryTypeCoercer.coercer_instance_for(type, strict)
62
- end
63
- end
64
-
65
- def self.cache_instance(type, method, strict, &_block)
66
- key = cache_key(type, method, strict)
67
-
68
- return @__cache[key] if @__cache.key?(key)
69
-
70
- instance = yield
71
-
72
- @__cache_write_lock.synchronize do
73
- @__cache[key] = instance
74
- end
75
-
76
- instance
77
- end
78
-
79
- def self.cache_key(type, method, strict)
80
- [type, method, strict].each_with_object(+'_') do |val, memo|
81
- next if val.nil?
82
-
83
- memo << '_' << val.to_s
84
- end
85
- end
86
-
87
- instance_variable_set(:@__cache, {})
88
- instance_variable_set(:@__cache_write_lock, Mutex.new)
89
- end
90
- end
91
- end
92
- end