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/api.rb
CHANGED
@@ -5,7 +5,7 @@ module Grape
|
|
5
5
|
# should subclass this class in order to build an API.
|
6
6
|
class API
|
7
7
|
# Class methods that we want to call on the API rather than on the API object
|
8
|
-
NON_OVERRIDABLE = %i[call call! configuration compile! inherited].freeze
|
8
|
+
NON_OVERRIDABLE = %i[call call! configuration compile! inherited recognize_path].freeze
|
9
9
|
|
10
10
|
class Boolean
|
11
11
|
def self.build(val)
|
@@ -20,12 +20,18 @@ module Grape
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class << self
|
23
|
+
extend Forwardable
|
23
24
|
attr_accessor :base_instance, :instances
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
delegate_missing_to :base_instance
|
27
|
+
def_delegators :base_instance, :new, :configuration
|
28
|
+
|
29
|
+
# This is the interface point between Rack and Grape; it accepts a request
|
30
|
+
# from Rack and ultimately returns an array of three values: the status,
|
31
|
+
# the headers, and the body. See [the rack specification]
|
32
|
+
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
|
33
|
+
# NOTE: This will only be called on an API directly mounted on RACK
|
34
|
+
def_delegators :instance_for_rack, :call, :compile!
|
29
35
|
|
30
36
|
# When inherited, will create a list of all instances (times the API was mounted)
|
31
37
|
# It will listen to the setup required to mount that endpoint, and replicate it on any new instance
|
@@ -40,7 +46,7 @@ module Grape
|
|
40
46
|
# an instance that will be used to create the set up but will not be mounted
|
41
47
|
def initial_setup(base_instance_parent)
|
42
48
|
@instances = []
|
43
|
-
@setup =
|
49
|
+
@setup = []
|
44
50
|
@base_parent = base_instance_parent
|
45
51
|
@base_instance = mount_instance
|
46
52
|
end
|
@@ -49,7 +55,7 @@ module Grape
|
|
49
55
|
def override_all_methods!
|
50
56
|
(base_instance.methods - Class.methods - NON_OVERRIDABLE).each do |method_override|
|
51
57
|
define_singleton_method(method_override) do |*args, &block|
|
52
|
-
add_setup(method_override,
|
58
|
+
add_setup(method: method_override, args: args, block: block)
|
53
59
|
end
|
54
60
|
end
|
55
61
|
end
|
@@ -69,67 +75,28 @@ module Grape
|
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
72
|
-
# This is the interface point between Rack and Grape; it accepts a request
|
73
|
-
# from Rack and ultimately returns an array of three values: the status,
|
74
|
-
# the headers, and the body. See [the rack specification]
|
75
|
-
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
|
76
|
-
# NOTE: This will only be called on an API directly mounted on RACK
|
77
|
-
def call(...)
|
78
|
-
instance_for_rack.call(...)
|
79
|
-
end
|
80
|
-
|
81
|
-
# Alleviates problems with autoloading by tring to search for the constant
|
82
|
-
def const_missing(*args)
|
83
|
-
if base_instance.const_defined?(*args)
|
84
|
-
base_instance.const_get(*args)
|
85
|
-
else
|
86
|
-
super
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
78
|
# The remountable class can have a configuration hash to provide some dynamic class-level variables.
|
91
79
|
# For instance, a description could be done using: `desc configuration[:description]` if it may vary
|
92
80
|
# depending on where the endpoint is mounted. Use with care, if you find yourself using configuration
|
93
81
|
# too much, you may actually want to provide a new API rather than remount it.
|
94
|
-
def mount_instance(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
82
|
+
def mount_instance(configuration: nil)
|
83
|
+
Class.new(@base_parent).tap do |instance|
|
84
|
+
instance.configuration = Grape::Util::EndpointConfiguration.new(configuration || {})
|
85
|
+
instance.base = self
|
86
|
+
replay_setup_on(instance)
|
87
|
+
end
|
100
88
|
end
|
101
89
|
|
90
|
+
private
|
91
|
+
|
102
92
|
# Replays the set up to produce an API as defined in this class, can be called
|
103
93
|
# on classes that inherit from Grape::API
|
104
94
|
def replay_setup_on(instance)
|
105
95
|
@setup.each do |setup_step|
|
106
|
-
replay_step_on(instance, setup_step)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def respond_to?(method, include_private = false)
|
111
|
-
super || base_instance.respond_to?(method, include_private)
|
112
|
-
end
|
113
|
-
|
114
|
-
def respond_to_missing?(method, include_private = false)
|
115
|
-
base_instance.respond_to?(method, include_private)
|
116
|
-
end
|
117
|
-
|
118
|
-
def method_missing(method, *args, &block)
|
119
|
-
# If there's a missing method, it may be defined on the base_instance instead.
|
120
|
-
if respond_to_missing?(method)
|
121
|
-
base_instance.send(method, *args, &block)
|
122
|
-
else
|
123
|
-
super
|
96
|
+
replay_step_on(instance, **setup_step)
|
124
97
|
end
|
125
98
|
end
|
126
99
|
|
127
|
-
def compile!
|
128
|
-
instance_for_rack.compile! # See API::Instance.compile!
|
129
|
-
end
|
130
|
-
|
131
|
-
private
|
132
|
-
|
133
100
|
def instance_for_rack
|
134
101
|
if never_mounted?
|
135
102
|
base_instance
|
@@ -139,34 +106,35 @@ module Grape
|
|
139
106
|
end
|
140
107
|
|
141
108
|
# Adds a new stage to the set up require to get a Grape::API up and running
|
142
|
-
def add_setup(
|
143
|
-
|
144
|
-
@setup += [setup_step]
|
109
|
+
def add_setup(step)
|
110
|
+
@setup << step
|
145
111
|
last_response = nil
|
146
112
|
@instances.each do |instance|
|
147
|
-
last_response = replay_step_on(instance,
|
113
|
+
last_response = replay_step_on(instance, **step)
|
148
114
|
end
|
149
115
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
116
|
+
refresh_mount_step if step[:method] != :mount
|
117
|
+
last_response
|
118
|
+
end
|
119
|
+
|
120
|
+
# Updating all previously mounted classes in the case that new methods have been executed.
|
121
|
+
def refresh_mount_step
|
122
|
+
@setup.each do |setup_step|
|
123
|
+
next if setup_step[:method] != :mount
|
124
|
+
|
125
|
+
refresh_mount_step = setup_step.merge(method: :refresh_mounted_api)
|
126
|
+
@setup << refresh_mount_step
|
127
|
+
@instances.each do |instance|
|
128
|
+
replay_step_on(instance, **refresh_mount_step)
|
159
129
|
end
|
160
130
|
end
|
161
|
-
|
162
|
-
last_response
|
163
131
|
end
|
164
132
|
|
165
|
-
def replay_step_on(instance,
|
166
|
-
return if skip_immediate_run?(instance,
|
133
|
+
def replay_step_on(instance, method:, args:, block:)
|
134
|
+
return if skip_immediate_run?(instance, args)
|
167
135
|
|
168
|
-
|
169
|
-
response = instance.send(
|
136
|
+
eval_args = evaluate_arguments(instance.configuration, *args)
|
137
|
+
response = instance.send(method, *eval_args, &block)
|
170
138
|
if skip_immediate_run?(instance, [response])
|
171
139
|
response
|
172
140
|
else
|
@@ -181,12 +149,12 @@ module Grape
|
|
181
149
|
end
|
182
150
|
|
183
151
|
def any_lazy?(args)
|
184
|
-
args.any? { |argument| argument.
|
152
|
+
args.any? { |argument| argument.try(:lazy?) }
|
185
153
|
end
|
186
154
|
|
187
155
|
def evaluate_arguments(configuration, *args)
|
188
156
|
args.map do |argument|
|
189
|
-
if argument.
|
157
|
+
if argument.try(:lazy?)
|
190
158
|
argument.evaluate_from(configuration)
|
191
159
|
elsif argument.is_a?(Hash)
|
192
160
|
argument.transform_values { |value| evaluate_arguments(configuration, value).first }
|
data/lib/grape/cookies.rb
CHANGED
@@ -2,43 +2,49 @@
|
|
2
2
|
|
3
3
|
module Grape
|
4
4
|
class Cookies
|
5
|
-
|
6
|
-
@cookies = {}
|
7
|
-
@send_cookies = {}
|
8
|
-
end
|
5
|
+
extend Forwardable
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
DELETED_COOKIES_ATTRS = {
|
8
|
+
max_age: '0',
|
9
|
+
value: '',
|
10
|
+
expires: Time.at(0)
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def_delegators :cookies, :[], :each
|
14
|
+
|
15
|
+
def initialize(rack_cookies)
|
16
|
+
@cookies = rack_cookies
|
17
|
+
@send_cookies = nil
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
def response_cookies
|
21
|
+
return unless @send_cookies
|
22
|
+
|
23
|
+
send_cookies.each do |name|
|
24
|
+
yield name, cookies[name]
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
23
|
-
def [](name)
|
24
|
-
|
28
|
+
def []=(name, value)
|
29
|
+
cookies[name] = value
|
30
|
+
send_cookies << name
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
|
33
|
+
# see https://github.com/rack/rack/blob/main/lib/rack/utils.rb#L338-L340
|
34
|
+
def delete(name, **opts)
|
35
|
+
self.[]=(name, opts.merge(DELETED_COOKIES_ATTRS))
|
30
36
|
end
|
31
37
|
|
32
|
-
|
33
|
-
|
38
|
+
private
|
39
|
+
|
40
|
+
def cookies
|
41
|
+
return @cookies unless @cookies.is_a?(Proc)
|
42
|
+
|
43
|
+
@cookies = @cookies.call.with_indifferent_access
|
34
44
|
end
|
35
45
|
|
36
|
-
|
37
|
-
|
38
|
-
def delete(name, **opts)
|
39
|
-
options = opts.merge(max_age: '0', value: '', expires: Time.at(0))
|
40
|
-
self.[]=(name, options)
|
46
|
+
def send_cookies
|
47
|
+
@send_cookies ||= Set.new
|
41
48
|
end
|
42
|
-
# rubocop:enable Layout/SpaceBeforeBrackets
|
43
49
|
end
|
44
50
|
end
|
data/lib/grape/dsl/api.rb
CHANGED
data/lib/grape/dsl/desc.rb
CHANGED
@@ -70,33 +70,23 @@ module Grape
|
|
70
70
|
# # ...
|
71
71
|
# end
|
72
72
|
#
|
73
|
-
def desc(description, options =
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
elsif configuration.is_a?(Hash)
|
81
|
-
configuration
|
82
|
-
end
|
83
|
-
end
|
84
|
-
endpoint_configuration ||= {}
|
85
|
-
config_class = desc_container(endpoint_configuration)
|
73
|
+
def desc(description, options = nil, &config_block)
|
74
|
+
opts =
|
75
|
+
if config_block
|
76
|
+
desc_container(endpoint_configuration).then do |config_class|
|
77
|
+
config_class.configure do
|
78
|
+
description(description)
|
79
|
+
end
|
86
80
|
|
87
|
-
|
88
|
-
|
81
|
+
config_class.configure(&config_block)
|
82
|
+
config_class.settings
|
83
|
+
end
|
84
|
+
else
|
85
|
+
options&.merge(description: description) || { description: description }
|
89
86
|
end
|
90
87
|
|
91
|
-
|
92
|
-
|
93
|
-
options = config_class.settings
|
94
|
-
else
|
95
|
-
options = options.merge(description: description)
|
96
|
-
end
|
97
|
-
|
98
|
-
namespace_setting :description, options
|
99
|
-
route_setting :description, options
|
88
|
+
namespace_setting :description, opts
|
89
|
+
route_setting :description, opts
|
100
90
|
end
|
101
91
|
|
102
92
|
# Returns an object which configures itself via an instance-context DSL.
|
@@ -116,6 +106,19 @@ module Grape
|
|
116
106
|
end
|
117
107
|
end
|
118
108
|
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def endpoint_configuration
|
113
|
+
return {} unless defined?(configuration)
|
114
|
+
|
115
|
+
if configuration.respond_to?(:evaluate)
|
116
|
+
configuration.evaluate
|
117
|
+
# Within `given` or `mounted blocks` the configuration is already evaluated
|
118
|
+
elsif configuration.is_a?(Hash)
|
119
|
+
configuration
|
120
|
+
end
|
121
|
+
end
|
119
122
|
end
|
120
123
|
end
|
121
124
|
end
|
data/lib/grape/dsl/headers.rb
CHANGED
@@ -10,7 +10,7 @@ module Grape
|
|
10
10
|
# 4. Delete a specifc header key-value pair
|
11
11
|
def header(key = nil, val = nil)
|
12
12
|
if key
|
13
|
-
val ? header[key
|
13
|
+
val ? header[key] = val : header.delete(key)
|
14
14
|
else
|
15
15
|
@header ||= Grape::Util::Header.new
|
16
16
|
end
|
data/lib/grape/dsl/helpers.rb
CHANGED
@@ -98,7 +98,7 @@ module Grape
|
|
98
98
|
protected
|
99
99
|
|
100
100
|
def process_named_params
|
101
|
-
return
|
101
|
+
return if @named_params.blank?
|
102
102
|
|
103
103
|
api.namespace_stackable(:named_params, @named_params)
|
104
104
|
end
|
@@ -26,8 +26,8 @@ module Grape
|
|
26
26
|
# has completed
|
27
27
|
module PostBeforeFilter
|
28
28
|
def declared(passed_params, options = {}, declared_params = nil, params_nested_path = [])
|
29
|
-
options
|
30
|
-
declared_params ||= optioned_declared_params(
|
29
|
+
options.reverse_merge!(include_missing: true, include_parent_namespaces: true, evaluate_given: false)
|
30
|
+
declared_params ||= optioned_declared_params(options[:include_parent_namespaces])
|
31
31
|
|
32
32
|
res = if passed_params.is_a?(Array)
|
33
33
|
declared_array(passed_params, options, declared_params, params_nested_path)
|
@@ -79,7 +79,7 @@ module Grape
|
|
79
79
|
else
|
80
80
|
# If it is not a Hash then it does not have children.
|
81
81
|
# Find its value or set it to nil.
|
82
|
-
return unless options[:include_missing] || passed_params.key
|
82
|
+
return unless options[:include_missing] || passed_params.try(:key?, declared_param)
|
83
83
|
|
84
84
|
rename_path = params_nested_path + [declared_param.to_s]
|
85
85
|
renamed_param_name = renamed_params[rename_path]
|
@@ -107,7 +107,7 @@ module Grape
|
|
107
107
|
|
108
108
|
if type == 'Hash' && !has_children
|
109
109
|
{}
|
110
|
-
elsif type == 'Array' || (type&.start_with?('[') && type
|
110
|
+
elsif type == 'Array' || (type&.start_with?('[') && type.exclude?(','))
|
111
111
|
[]
|
112
112
|
elsif type == 'Set' || type&.start_with?('#<Set')
|
113
113
|
Set.new
|
@@ -120,8 +120,8 @@ module Grape
|
|
120
120
|
options[:stringify] ? declared_param.to_s : declared_param.to_sym
|
121
121
|
end
|
122
122
|
|
123
|
-
def optioned_declared_params(
|
124
|
-
declared_params = if
|
123
|
+
def optioned_declared_params(include_parent_namespaces)
|
124
|
+
declared_params = if include_parent_namespaces
|
125
125
|
# Declared params including parent namespaces
|
126
126
|
route_setting(:declared_params)
|
127
127
|
else
|
@@ -199,10 +199,9 @@ module Grape
|
|
199
199
|
# Redirect to a new url.
|
200
200
|
#
|
201
201
|
# @param url [String] The url to be redirect.
|
202
|
-
# @param
|
203
|
-
#
|
204
|
-
|
205
|
-
def redirect(url, permanent: false, body: nil, **_options)
|
202
|
+
# @param permanent [Boolean] default false.
|
203
|
+
# @param body default a short message including the URL.
|
204
|
+
def redirect(url, permanent: false, body: nil)
|
206
205
|
body_message = body
|
207
206
|
if permanent
|
208
207
|
status 301
|
@@ -214,7 +213,7 @@ module Grape
|
|
214
213
|
status 302
|
215
214
|
body_message ||= "This resource has been moved temporarily to #{url}."
|
216
215
|
end
|
217
|
-
header
|
216
|
+
header 'Location', url
|
218
217
|
content_type 'text/plain'
|
219
218
|
body body_message
|
220
219
|
end
|
@@ -258,18 +257,6 @@ module Grape
|
|
258
257
|
end
|
259
258
|
end
|
260
259
|
|
261
|
-
# Set or get a cookie
|
262
|
-
#
|
263
|
-
# @example
|
264
|
-
# cookies[:mycookie] = 'mycookie val'
|
265
|
-
# cookies['mycookie-string'] = 'mycookie string val'
|
266
|
-
# cookies[:more] = { value: '123', expires: Time.at(0) }
|
267
|
-
# cookies.delete :more
|
268
|
-
#
|
269
|
-
def cookies
|
270
|
-
@cookies ||= Cookies.new
|
271
|
-
end
|
272
|
-
|
273
260
|
# Allows you to define the response body as something other than the
|
274
261
|
# return value.
|
275
262
|
#
|
@@ -305,20 +292,6 @@ module Grape
|
|
305
292
|
body false
|
306
293
|
end
|
307
294
|
|
308
|
-
# Deprecated method to send files to the client. Use `sendfile` or `stream`
|
309
|
-
def file(value = nil)
|
310
|
-
if value.is_a?(String)
|
311
|
-
Grape.deprecator.warn('Use sendfile or stream to send files.')
|
312
|
-
sendfile(value)
|
313
|
-
elsif !value.is_a?(NilClass)
|
314
|
-
Grape.deprecator.warn('Use stream to use a Stream object.')
|
315
|
-
stream(value)
|
316
|
-
else
|
317
|
-
Grape.deprecator.warn('Use sendfile or stream to send files.')
|
318
|
-
sendfile
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
295
|
# Allows you to send a file to the client via sendfile.
|
323
296
|
#
|
324
297
|
# @example
|
@@ -357,7 +330,7 @@ module Grape
|
|
357
330
|
return if value.nil? && @stream.nil?
|
358
331
|
|
359
332
|
header Rack::CONTENT_LENGTH, nil
|
360
|
-
header
|
333
|
+
header 'Transfer-Encoding', nil
|
361
334
|
header Rack::CACHE_CONTROL, 'no-cache' # Skips ETag generation (reading the response up front)
|
362
335
|
if value.is_a?(String)
|
363
336
|
file_body = Grape::ServeStream::FileBody.new(value)
|
@@ -462,11 +435,15 @@ module Grape
|
|
462
435
|
def entity_representation_for(entity_class, object, options)
|
463
436
|
embeds = { env: env }
|
464
437
|
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
465
|
-
entity_class.represent(object, **embeds
|
438
|
+
entity_class.represent(object, **embeds, **options)
|
466
439
|
end
|
467
440
|
|
468
441
|
def http_version
|
469
|
-
env
|
442
|
+
env.fetch('HTTP_VERSION') { env[Rack::SERVER_PROTOCOL] }
|
443
|
+
end
|
444
|
+
|
445
|
+
def api_format(format)
|
446
|
+
env[Grape::Env::API_FORMAT] = format
|
470
447
|
end
|
471
448
|
|
472
449
|
def context
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -23,14 +23,14 @@ module Grape
|
|
23
23
|
# class API < Grape::API
|
24
24
|
# desc "Get collection"
|
25
25
|
# params do
|
26
|
-
# build_with
|
26
|
+
# build_with :hashie_mash
|
27
27
|
# requires :user_id, type: Integer
|
28
28
|
# end
|
29
29
|
# get do
|
30
30
|
# params['user_id']
|
31
31
|
# end
|
32
32
|
# end
|
33
|
-
def build_with(build_with
|
33
|
+
def build_with(build_with)
|
34
34
|
@api.namespace_inheritable(:build_params_with, build_with)
|
35
35
|
end
|
36
36
|
|
@@ -136,7 +136,7 @@ module Grape
|
|
136
136
|
require_required_and_optional_fields(attrs.first, opts)
|
137
137
|
else
|
138
138
|
validate_attributes(attrs, opts, &block)
|
139
|
-
block ? new_scope(orig_attrs, &block) : push_declared_params(attrs,
|
139
|
+
block ? new_scope(orig_attrs, &block) : push_declared_params(attrs, opts.slice(:as))
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
@@ -162,7 +162,7 @@ module Grape
|
|
162
162
|
else
|
163
163
|
validate_attributes(attrs, opts, &block)
|
164
164
|
|
165
|
-
block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs,
|
165
|
+
block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, opts.slice(:as))
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
@@ -251,7 +251,7 @@ module Grape
|
|
251
251
|
# @return hash of parameters relevant for the current scope
|
252
252
|
# @api private
|
253
253
|
def params(params)
|
254
|
-
params = @parent.params(params) if instance_variable_defined?(:@parent) && @parent
|
254
|
+
params = @parent.params_meeting_dependency.presence || @parent.params(params) if instance_variable_defined?(:@parent) && @parent
|
255
255
|
params = map_params(params, @element) if instance_variable_defined?(:@element) && @element
|
256
256
|
params
|
257
257
|
end
|
data/lib/grape/dsl/routing.rb
CHANGED
@@ -67,6 +67,10 @@ module Grape
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
def build_with(build_with)
|
71
|
+
namespace_inheritable(:build_params_with, build_with)
|
72
|
+
end
|
73
|
+
|
70
74
|
# Do not route HEAD requests to GET requests automatically.
|
71
75
|
def do_not_route_head!
|
72
76
|
namespace_inheritable(:do_not_route_head, true)
|
@@ -77,6 +81,10 @@ module Grape
|
|
77
81
|
namespace_inheritable(:do_not_route_options, true)
|
78
82
|
end
|
79
83
|
|
84
|
+
def lint!
|
85
|
+
namespace_inheritable(:lint, true)
|
86
|
+
end
|
87
|
+
|
80
88
|
def do_not_document!
|
81
89
|
namespace_inheritable(:do_not_document, true)
|
82
90
|
end
|
@@ -154,7 +162,7 @@ module Grape
|
|
154
162
|
reset_validations!
|
155
163
|
end
|
156
164
|
|
157
|
-
Grape::
|
165
|
+
Grape::HTTP_SUPPORTED_METHODS.each do |supported_method|
|
158
166
|
define_method supported_method.downcase do |*args, &block|
|
159
167
|
options = args.extract_options!
|
160
168
|
paths = args.first || ['/']
|
@@ -175,19 +183,12 @@ module Grape
|
|
175
183
|
# end
|
176
184
|
# end
|
177
185
|
def namespace(space = nil, options = {}, &block)
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
@namespace_description = (@namespace_description || {}).deep_merge(namespace_setting(:description) || {})
|
184
|
-
nest(block) do
|
185
|
-
namespace_stackable(:namespace, Namespace.new(space, **options)) if space
|
186
|
-
end
|
187
|
-
@namespace_description = previous_namespace_description
|
186
|
+
return Namespace.joined_space_path(namespace_stackable(:namespace)) unless space || block
|
187
|
+
|
188
|
+
within_namespace do
|
189
|
+
nest(block) do
|
190
|
+
namespace_stackable(:namespace, Namespace.new(space, options)) if space
|
188
191
|
end
|
189
|
-
else
|
190
|
-
Namespace.joined_space_path(namespace_stackable(:namespace))
|
191
192
|
end
|
192
193
|
end
|
193
194
|
|