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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +41 -18
- data/UPGRADING.md +75 -1
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +25 -60
- data/lib/grape/api.rb +44 -76
- data/lib/grape/cookies.rb +31 -25
- data/lib/grape/dsl/api.rb +0 -2
- data/lib/grape/dsl/desc.rb +27 -24
- data/lib/grape/dsl/headers.rb +1 -1
- data/lib/grape/dsl/helpers.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +17 -40
- data/lib/grape/dsl/parameters.rb +5 -5
- data/lib/grape/dsl/routing.rb +14 -13
- data/lib/grape/endpoint.rb +100 -106
- data/lib/grape/error_formatter/base.rb +51 -21
- data/lib/grape/error_formatter/json.rb +7 -24
- data/lib/grape/error_formatter/serializable_hash.rb +7 -0
- data/lib/grape/error_formatter/txt.rb +13 -20
- data/lib/grape/error_formatter/xml.rb +3 -13
- data/lib/grape/error_formatter.rb +4 -12
- data/lib/grape/exceptions/base.rb +18 -30
- data/lib/grape/exceptions/conflicting_types.rb +11 -0
- data/lib/grape/exceptions/invalid_parameters.rb +11 -0
- data/lib/grape/exceptions/too_deep_parameters.rb +11 -0
- data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
- data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
- data/lib/grape/exceptions/validation.rb +5 -4
- data/lib/grape/exceptions/validation_errors.rb +2 -2
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +2 -5
- data/lib/grape/extensions/hash.rb +2 -1
- data/lib/grape/extensions/hashie/mash.rb +3 -5
- data/lib/grape/formatter/base.rb +16 -0
- data/lib/grape/formatter/json.rb +4 -6
- data/lib/grape/formatter/serializable_hash.rb +1 -1
- data/lib/grape/formatter/txt.rb +3 -5
- data/lib/grape/formatter/xml.rb +4 -6
- data/lib/grape/formatter.rb +4 -12
- data/lib/grape/locale/en.yml +44 -44
- data/lib/grape/middleware/auth/base.rb +11 -32
- data/lib/grape/middleware/auth/dsl.rb +23 -29
- data/lib/grape/middleware/base.rb +30 -11
- data/lib/grape/middleware/error.rb +18 -24
- data/lib/grape/middleware/formatter.rb +39 -73
- data/lib/grape/middleware/stack.rb +26 -36
- data/lib/grape/middleware/versioner/accept_version_header.rb +1 -3
- data/lib/grape/middleware/versioner/base.rb +74 -0
- data/lib/grape/middleware/versioner/header.rb +4 -10
- data/lib/grape/middleware/versioner/param.rb +2 -5
- data/lib/grape/middleware/versioner/path.rb +0 -2
- data/lib/grape/middleware/versioner.rb +5 -3
- data/lib/grape/namespace.rb +1 -1
- data/lib/grape/params_builder/base.rb +18 -0
- data/lib/grape/params_builder/hash.rb +11 -0
- data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
- data/lib/grape/params_builder/hashie_mash.rb +11 -0
- data/lib/grape/params_builder.rb +32 -0
- data/lib/grape/parser/base.rb +16 -0
- data/lib/grape/parser/json.rb +6 -8
- data/lib/grape/parser/xml.rb +6 -8
- data/lib/grape/parser.rb +5 -7
- data/lib/grape/path.rb +39 -56
- data/lib/grape/request.rb +162 -23
- data/lib/grape/router/base_route.rb +2 -2
- data/lib/grape/router/greedy_route.rb +2 -2
- data/lib/grape/router/pattern.rb +23 -18
- data/lib/grape/router/route.rb +14 -6
- data/lib/grape/router.rb +30 -12
- data/lib/grape/util/registry.rb +27 -0
- data/lib/grape/validations/contract_scope.rb +2 -39
- data/lib/grape/validations/params_scope.rb +15 -14
- data/lib/grape/validations/types/dry_type_coercer.rb +10 -6
- data/lib/grape/validations/validator_factory.rb +2 -2
- data/lib/grape/validations/validators/allow_blank_validator.rb +1 -1
- data/lib/grape/validations/validators/base.rb +7 -11
- data/lib/grape/validations/validators/coerce_validator.rb +1 -1
- data/lib/grape/validations/validators/contract_scope_validator.rb +41 -0
- data/lib/grape/validations/validators/default_validator.rb +1 -1
- data/lib/grape/validations/validators/except_values_validator.rb +2 -2
- data/lib/grape/validations/validators/length_validator.rb +1 -1
- data/lib/grape/validations/validators/presence_validator.rb +1 -1
- data/lib/grape/validations/validators/regexp_validator.rb +2 -2
- data/lib/grape/validations/validators/values_validator.rb +15 -57
- data/lib/grape/validations.rb +8 -17
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +14 -2
- metadata +24 -16
- data/lib/grape/http/headers.rb +0 -55
- data/lib/grape/middleware/helpers.rb +0 -12
- data/lib/grape/middleware/versioner_helpers.rb +0 -75
- data/lib/grape/util/lazy/object.rb +0 -45
- data/lib/grape/validations/types/build_coercer.rb +0 -92
data/lib/grape/http/headers.rb
DELETED
@@ -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,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
|