grape 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +7 -6
  4. data/UPGRADING.md +19 -0
  5. data/grape.gemspec +5 -5
  6. data/lib/grape/api/instance.rb +22 -58
  7. data/lib/grape/api.rb +2 -11
  8. data/lib/grape/dsl/desc.rb +27 -24
  9. data/lib/grape/dsl/inside_route.rb +12 -23
  10. data/lib/grape/dsl/parameters.rb +2 -2
  11. data/lib/grape/dsl/routing.rb +5 -12
  12. data/lib/grape/endpoint.rb +76 -79
  13. data/lib/grape/error_formatter/base.rb +51 -21
  14. data/lib/grape/error_formatter/json.rb +7 -24
  15. data/lib/grape/error_formatter/jsonapi.rb +7 -0
  16. data/lib/grape/error_formatter/serializable_hash.rb +7 -0
  17. data/lib/grape/error_formatter/txt.rb +13 -20
  18. data/lib/grape/error_formatter/xml.rb +3 -13
  19. data/lib/grape/error_formatter.rb +4 -12
  20. data/lib/grape/exceptions/base.rb +18 -30
  21. data/lib/grape/exceptions/validation.rb +5 -4
  22. data/lib/grape/exceptions/validation_errors.rb +2 -2
  23. data/lib/grape/formatter/base.rb +16 -0
  24. data/lib/grape/formatter/json.rb +4 -6
  25. data/lib/grape/formatter/serializable_hash.rb +1 -1
  26. data/lib/grape/formatter/txt.rb +3 -5
  27. data/lib/grape/formatter/xml.rb +4 -6
  28. data/lib/grape/formatter.rb +4 -12
  29. data/lib/grape/http/headers.rb +1 -0
  30. data/lib/grape/middleware/error.rb +2 -0
  31. data/lib/grape/middleware/formatter.rb +1 -1
  32. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -3
  33. data/lib/grape/middleware/versioner/base.rb +82 -0
  34. data/lib/grape/middleware/versioner/header.rb +3 -9
  35. data/lib/grape/middleware/versioner/param.rb +0 -2
  36. data/lib/grape/middleware/versioner/path.rb +0 -2
  37. data/lib/grape/middleware/versioner.rb +5 -3
  38. data/lib/grape/namespace.rb +1 -1
  39. data/lib/grape/parser/base.rb +16 -0
  40. data/lib/grape/parser/json.rb +6 -8
  41. data/lib/grape/parser/jsonapi.rb +7 -0
  42. data/lib/grape/parser/xml.rb +6 -8
  43. data/lib/grape/parser.rb +5 -7
  44. data/lib/grape/path.rb +39 -56
  45. data/lib/grape/request.rb +2 -2
  46. data/lib/grape/router/base_route.rb +2 -2
  47. data/lib/grape/router/greedy_route.rb +2 -2
  48. data/lib/grape/router/pattern.rb +23 -18
  49. data/lib/grape/router/route.rb +13 -5
  50. data/lib/grape/router.rb +5 -5
  51. data/lib/grape/util/registry.rb +27 -0
  52. data/lib/grape/validations/contract_scope.rb +2 -39
  53. data/lib/grape/validations/params_scope.rb +7 -11
  54. data/lib/grape/validations/types/dry_type_coercer.rb +10 -6
  55. data/lib/grape/validations/validator_factory.rb +2 -2
  56. data/lib/grape/validations/validators/allow_blank_validator.rb +1 -1
  57. data/lib/grape/validations/validators/base.rb +5 -9
  58. data/lib/grape/validations/validators/coerce_validator.rb +1 -1
  59. data/lib/grape/validations/validators/contract_scope_validator.rb +41 -0
  60. data/lib/grape/validations/validators/default_validator.rb +1 -1
  61. data/lib/grape/validations/validators/except_values_validator.rb +1 -1
  62. data/lib/grape/validations/validators/length_validator.rb +1 -1
  63. data/lib/grape/validations/validators/regexp_validator.rb +1 -1
  64. data/lib/grape/validations/validators/values_validator.rb +15 -57
  65. data/lib/grape/validations.rb +8 -17
  66. data/lib/grape/version.rb +1 -1
  67. data/lib/grape.rb +1 -1
  68. metadata +14 -11
  69. data/lib/grape/middleware/versioner_helpers.rb +0 -75
  70. data/lib/grape/validations/types/build_coercer.rb +0 -92
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc04f424b8181e92cc304d02d2923952f07e2532ef0291233596813726a2cb68
4
- data.tar.gz: 46729a20982fc16129540a81061bea229fd3ba5dd81426c1830119b52fe6ccd2
3
+ metadata.gz: eefbc6eed618a448bcc9657c03ca73f5771f22b5f13b4c56cacb7ec7e05750ac
4
+ data.tar.gz: 6506e73d4ce49cdf54c142acee7085217bd6f55211f86b74a50d23a83ae48c02
5
5
  SHA512:
6
- metadata.gz: 45e47b5059a37bbf75331c41bb1fdda2487610e3713baf5b8181dcbbae1727c47995503f5dc8a12375fd0765908140540100579afe834dfe96dc4c07cd771b2f
7
- data.tar.gz: 9692f64fc61714c33035ef59c0d68a9c34fb3725a5842e0fe16cbd4d7025265bef50ea5086a3f61d5ed1f0fd8740435619ff616eed55e45fd3cc48e090a02b7d
6
+ metadata.gz: 6e5dab9502a1484f267e9881b8a368cfe809f47eaf9870d14db2002c63c48863f92bbd561c54dd81b0c4e4ff416a7fa7abc121c0052576dc0d7cb088d425d282
7
+ data.tar.gz: e78c3fc83ae2a908ef510a387cd31060a13eeb23d7d209c842f2d7e64286ca21e506472fd7ca9f397e1169f7e74fc439a097c376d4ba6682b1c091009fc52acd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ### 2.3.0 (2025-02-08)
2
+
3
+ #### Features
4
+
5
+ * [#2497](https://github.com/ruby-grape/grape/pull/2497): Update RuboCop to 1.66.1 - [@ericproulx](https://github.com/ericproulx).
6
+ * [#2500](https://github.com/ruby-grape/grape/pull/2500): Remove deprecated `file` method - [@ericproulx](https://github.com/ericproulx).
7
+ * [#2501](https://github.com/ruby-grape/grape/pull/2501): Remove deprecated `except` and `proc` options in values validator - [@ericproulx](https://github.com/ericproulx).
8
+ * [#2502](https://github.com/ruby-grape/grape/pull/2502): Remove deprecation `options` in `desc` - [@ericproulx](https://github.com/ericproulx).
9
+ * [#2512](https://github.com/ruby-grape/grape/pull/2512): Optimize hash alloc - [@ericproulx](https://github.com/ericproulx).
10
+ * [#2513](https://github.com/ruby-grape/grape/pull/2513): Optimize Grape::Path - [@ericproulx](https://github.com/ericproulx).
11
+ * [#2514](https://github.com/ruby-grape/grape/pull/2514): Add rails 8.0 to CI - [@ericproulx](https://github.com/ericproulx).
12
+ * [#2516](https://github.com/ruby-grape/grape/pull/2516): Dynamic registration for parsers, formatters, versioners - [@ericproulx](https://github.com/ericproulx).
13
+ * [#2518](https://github.com/ruby-grape/grape/pull/2518): Add ruby 3.4 to CI - [@ericproulx](https://github.com/ericproulx).
14
+
15
+ #### Fixes
16
+
17
+ * [#2504](https://github.com/ruby-grape/grape/pull/2504): Fix leaky modules in specs - [@ericproulx](https://github.com/ericproulx).
18
+ * [#2506](https://github.com/ruby-grape/grape/pull/2506): Fix fetch_formatter api_format - [@ericproulx](https://github.com/ericproulx).
19
+ * [#2507](https://github.com/ruby-grape/grape/pull/2507): Fix type: Set with values - [@nikolai-b](https://github.com/nikolai-b).
20
+ * [#2510](https://github.com/ruby-grape/grape/pull/2510): Fix ContractScope's validator inheritance - [@ericproulx](https://github.com/ericproulx).
21
+ * [#2521](https://github.com/ruby-grape/grape/pull/2521): Fixed typo in README - [@datpmt](https://github.com/datpmt).
22
+ * [#2525](https://github.com/ruby-grape/grape/pull/2525): Require logger before active_support - [@ericproulx](https://github.com/ericproulx).
23
+ * [#2524](https://github.com/ruby-grape/grape/pull/2524): Fix validators bad encoding - [@ericproulx](https://github.com/ericproulx).
24
+ * [#2530](https://github.com/ruby-grape/grape/pull/2530): Fix endpoint's status when rescue_from without a block - [@ericproulx](https://github.com/ericproulx).
25
+ * [#2529](https://github.com/ruby-grape/grape/pull/2529): Fix missing settings on mounted routes (when settings are identical) - [@Haerezis](https://github.com/Haerezis).
26
+
1
27
  ### 2.2.0 (2024-09-14)
2
28
 
3
29
  #### Features
data/README.md CHANGED
@@ -157,7 +157,8 @@ Grape is a REST-like API framework for Ruby. It's designed to run on Rack or com
157
157
 
158
158
  ## Stable Release
159
159
 
160
- You're reading the documentation for the stable release of Grape, 2.2.0. Please read UPGRADING when upgrading from a previous version.
160
+ You're reading the documentation for the next release of Grape, 2.3.0.
161
+ Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
161
162
 
162
163
  ## Project Resources
163
164
 
@@ -2045,7 +2046,7 @@ end
2045
2046
  ```ruby
2046
2047
  params do
2047
2048
  requires :code, type: String, length: { is: 2, message: 'code is expected to be exactly 2 characters long' }
2048
- requires :str, type: String, length: { min: 5, message: 'str is expected to be atleast 5 characters long' }
2049
+ requires :str, type: String, length: { min: 5, message: 'str is expected to be at least 5 characters long' }
2049
2050
  requires :list, type: [Integer], length: { min: 2, max: 3, message: 'list is expected to have between 2 and 3 elements' }
2050
2051
  end
2051
2052
  ```
@@ -3065,7 +3066,7 @@ end
3065
3066
  * `GET /hello.xls` with an `Accept: application/xml` header has an unrecognized extension, but the `Accept` header corresponds to a recognized format, so it will respond with XML.
3066
3067
  * `GET /hello.xls` with an `Accept: text/plain` header has an unrecognized extension *and* an unrecognized `Accept` header, so it will respond with JSON (the default format).
3067
3068
 
3068
- You can override this process explicitly by specifying `env['api.format']` in the API itself.
3069
+ You can override this process explicitly by calling `api_format` in the API itself.
3069
3070
  For example, the following API will let you upload arbitrary files and return their contents as an attachment with the correct MIME type.
3070
3071
 
3071
3072
  ```ruby
@@ -3073,7 +3074,7 @@ class Twitter::API < Grape::API
3073
3074
  post 'attachment' do
3074
3075
  filename = params[:file][:filename]
3075
3076
  content_type MIME::Types.type_for(filename)[0].to_s
3076
- env['api.format'] = :binary # there's no formatter for :binary, data will be returned "as is"
3077
+ api_format :binary # there's no formatter for :binary, data will be returned "as is"
3077
3078
  header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(filename)}"
3078
3079
  params[:file][:tempfile].read
3079
3080
  end
@@ -3535,8 +3536,8 @@ Please use `Route#xyz` instead.
3535
3536
 
3536
3537
  Note that difference of `Route#options` and `Route#settings`.
3537
3538
 
3538
- The `options` can be referred from your route, it should be set by specifing key and value on verb methods such as `get`, `post` and `put`.
3539
- The `settings` can also be referred from your route, but it should be set by specifing key and value on `route_setting`.
3539
+ The `options` can be referred from your route, it should be set by specifying key and value on verb methods such as `get`, `post` and `put`.
3540
+ The `settings` can also be referred from your route, but it should be set by specifying key and value on `route_setting`.
3540
3541
 
3541
3542
  ## Current Route and Endpoint
3542
3543
 
data/UPGRADING.md CHANGED
@@ -1,6 +1,25 @@
1
1
  Upgrading Grape
2
2
  ===============
3
3
 
4
+ ### Upgrading to >= 2.3.0
5
+
6
+ ### `content_type` vs `api.format` inside API
7
+
8
+ Before 2.3.0, `content_type` had priority over `env['api.format']` when set in an API, which was incorrect. The priority has been flipped and `env['api.format']` will be checked first.
9
+ In addition, the function `api_format` has been added. Instead of setting `env['api.format']` directly, you can call `api_format`.
10
+ See [#2506](https://github.com/ruby-grape/grape/pull/2506) for more information.
11
+
12
+ #### Remove Deprecated Methods and Options
13
+
14
+ - Deprecated `file` method has been removed. Use `send_file` or `stream`.
15
+ See [#2500](https://github.com/ruby-grape/grape/pull/2500) for more information.
16
+
17
+ - The `except` and `proc` options have been removed from the `values` validator. Use `except_values` validator or assign `proc` directly to `values`.
18
+ See [#2501](https://github.com/ruby-grape/grape/pull/2501) for more information.
19
+
20
+ - `Passing an options hash and a block to 'desc'` deprecation has been removed. Move all hash options to block instead.
21
+ See [#2502](https://github.com/ruby-grape/grape/pull/2502) for more information.
22
+
4
23
  ### Upgrading to >= 2.2.0
5
24
 
6
25
  ### `Length` validator
data/grape.gemspec CHANGED
@@ -21,11 +21,11 @@ Gem::Specification.new do |s|
21
21
  'rubygems_mfa_required' => 'true'
22
22
  }
23
23
 
24
- s.add_runtime_dependency 'activesupport', '>= 6'
25
- s.add_runtime_dependency 'dry-types', '>= 1.1'
26
- s.add_runtime_dependency 'mustermann-grape', '~> 1.1.0'
27
- s.add_runtime_dependency 'rack', '>= 2'
28
- s.add_runtime_dependency 'zeitwerk'
24
+ s.add_dependency 'activesupport', '>= 6'
25
+ s.add_dependency 'dry-types', '>= 1.1'
26
+ s.add_dependency 'mustermann-grape', '~> 1.1.0'
27
+ s.add_dependency 'rack', '>= 2'
28
+ s.add_dependency 'zeitwerk'
29
29
 
30
30
  s.files = Dir['lib/**/*', 'CHANGELOG.md', 'CONTRIBUTING.md', 'README.md', 'grape.png', 'UPGRADING.md', 'LICENSE', 'grape.gemspec']
31
31
  s.require_paths = ['lib']
@@ -194,88 +194,52 @@ module Grape
194
194
  # will return an HTTP 405 response for any HTTP method that the resource
195
195
  # cannot handle.
196
196
  def add_head_not_allowed_methods_and_options_methods
197
- versioned_route_configs = collect_route_config_per_pattern
198
197
  # The paths we collected are prepared (cf. Path#prepare), so they
199
198
  # contain already versioning information when using path versioning.
199
+ all_routes = self.class.endpoints.map(&:routes).flatten
200
+
200
201
  # Disable versioning so adding a route won't prepend versioning
201
202
  # informations again.
202
- without_root_prefix do
203
- without_versioning do
204
- versioned_route_configs.each do |config|
205
- next if config[:options][:matching_wildchar]
206
-
207
- allowed_methods = config[:methods].dup
208
-
209
- allowed_methods |= [Rack::HEAD] if !self.class.namespace_inheritable(:do_not_route_head) && allowed_methods.include?(Rack::GET)
210
-
211
- allow_header = (self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Rack::OPTIONS] | allowed_methods)
212
-
213
- config[:endpoint].options[:options_route_enabled] = true unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Rack::OPTIONS)
214
-
215
- attributes = config.merge(allowed_methods: allowed_methods, allow_header: allow_header)
216
- generate_not_allowed_method(config[:pattern], **attributes)
217
- end
218
- end
219
- end
203
+ without_root_prefix_and_versioning { collect_route_config_per_pattern(all_routes) }
220
204
  end
221
205
 
222
- def collect_route_config_per_pattern
223
- all_routes = self.class.endpoints.map(&:routes).flatten
206
+ def collect_route_config_per_pattern(all_routes)
224
207
  routes_by_regexp = all_routes.group_by(&:pattern_regexp)
225
208
 
226
209
  # Build the configuration based on the first endpoint and the collection of methods supported.
227
- routes_by_regexp.values.map do |routes|
228
- last_route = routes.last # Most of the configuration is taken from the last endpoint
229
- matching_wildchar = routes.any? { |route| route.request_method == '*' }
230
- {
231
- options: { matching_wildchar: matching_wildchar },
232
- pattern: last_route.pattern,
233
- requirements: last_route.requirements,
234
- path: last_route.origin,
235
- endpoint: last_route.app,
236
- methods: matching_wildchar ? Grape::Http::Headers::SUPPORTED_METHODS : routes.map(&:request_method)
237
- }
238
- end
239
- end
210
+ routes_by_regexp.each_value do |routes|
211
+ last_route = routes.last # Most of the configuration is taken from the last endpoint
212
+ next if routes.any? { |route| route.request_method == '*' }
240
213
 
241
- # Generate a route that returns an HTTP 405 response for a user defined
242
- # path on methods not specified
243
- def generate_not_allowed_method(pattern, allowed_methods: [], **attributes)
244
- supported_methods =
245
- if self.class.namespace_inheritable(:do_not_route_options)
246
- Grape::Http::Headers::SUPPORTED_METHODS
247
- else
248
- Grape::Http::Headers::SUPPORTED_METHODS_WITHOUT_OPTIONS
249
- end
250
- not_allowed_methods = supported_methods - allowed_methods
251
- @router.associate_routes(pattern, not_allowed_methods: not_allowed_methods, **attributes)
214
+ allowed_methods = routes.map(&:request_method)
215
+ allowed_methods |= [Rack::HEAD] if !self.class.namespace_inheritable(:do_not_route_head) && allowed_methods.include?(Rack::GET)
216
+
217
+ allow_header = self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Rack::OPTIONS] | allowed_methods
218
+ last_route.app.options[:options_route_enabled] = true unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Rack::OPTIONS)
219
+
220
+ @router.associate_routes(last_route.pattern, {
221
+ endpoint: last_route.app,
222
+ allow_header: allow_header
223
+ })
224
+ end
252
225
  end
253
226
 
254
227
  # Allows definition of endpoints that ignore the versioning configuration
255
228
  # used by the rest of your API.
256
- def without_versioning(&_block)
229
+ def without_root_prefix_and_versioning
257
230
  old_version = self.class.namespace_inheritable(:version)
258
231
  old_version_options = self.class.namespace_inheritable(:version_options)
232
+ old_root_prefix = self.class.namespace_inheritable(:root_prefix)
259
233
 
260
234
  self.class.namespace_inheritable_to_nil(:version)
261
235
  self.class.namespace_inheritable_to_nil(:version_options)
236
+ self.class.namespace_inheritable_to_nil(:root_prefix)
262
237
 
263
238
  yield
264
239
 
265
240
  self.class.namespace_inheritable(:version, old_version)
266
241
  self.class.namespace_inheritable(:version_options, old_version_options)
267
- end
268
-
269
- # Allows definition of endpoints that ignore the root prefix used by the
270
- # rest of your API.
271
- def without_root_prefix(&_block)
272
- old_prefix = self.class.namespace_inheritable(:root_prefix)
273
-
274
- self.class.namespace_inheritable_to_nil(:root_prefix)
275
-
276
- yield
277
-
278
- self.class.namespace_inheritable(:root_prefix, old_prefix)
242
+ self.class.namespace_inheritable(:root_prefix, old_root_prefix)
279
243
  end
280
244
  end
281
245
  end
data/lib/grape/api.rb CHANGED
@@ -40,7 +40,7 @@ module Grape
40
40
  # an instance that will be used to create the set up but will not be mounted
41
41
  def initial_setup(base_instance_parent)
42
42
  @instances = []
43
- @setup = Set.new
43
+ @setup = []
44
44
  @base_parent = base_instance_parent
45
45
  @base_instance = mount_instance
46
46
  end
@@ -78,20 +78,11 @@ module Grape
78
78
  instance_for_rack.call(...)
79
79
  end
80
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
81
  # The remountable class can have a configuration hash to provide some dynamic class-level variables.
91
82
  # For instance, a description could be done using: `desc configuration[:description]` if it may vary
92
83
  # depending on where the endpoint is mounted. Use with care, if you find yourself using configuration
93
84
  # too much, you may actually want to provide a new API rather than remount it.
94
- def mount_instance(**opts)
85
+ def mount_instance(opts = {})
95
86
  instance = Class.new(@base_parent)
96
87
  instance.configuration = Grape::Util::EndpointConfiguration.new(opts[:configuration] || {})
97
88
  instance.base = self
@@ -70,33 +70,23 @@ module Grape
70
70
  # # ...
71
71
  # end
72
72
  #
73
- def desc(description, options = {}, &config_block)
74
- if config_block
75
- endpoint_configuration = if defined?(configuration)
76
- # When the instance is mounted - the configuration is executed on mount time
77
- if configuration.respond_to?(:evaluate)
78
- configuration.evaluate
79
- # Within `given` or `mounted blocks` the configuration is already evaluated
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
- config_class.configure do
88
- description description
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
- config_class.configure(&config_block)
92
- Grape.deprecator.warn('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') if options.any?
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
@@ -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 = options.reverse_merge(include_missing: true, include_parent_namespaces: true, evaluate_given: false)
30
- declared_params ||= optioned_declared_params(**options)
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)
@@ -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(**options)
124
- declared_params = if options[:include_parent_namespaces]
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 options [Hash] The options used when redirect.
203
- # :permanent, default false.
204
- # :body, default a short message including the URL.
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
@@ -305,20 +304,6 @@ module Grape
305
304
  body false
306
305
  end
307
306
 
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
307
  # Allows you to send a file to the client via sendfile.
323
308
  #
324
309
  # @example
@@ -466,7 +451,11 @@ module Grape
466
451
  end
467
452
 
468
453
  def http_version
469
- env['HTTP_VERSION'] || env[Rack::SERVER_PROTOCOL]
454
+ env.fetch(Grape::Http::Headers::HTTP_VERSION) { env[Rack::SERVER_PROTOCOL] }
455
+ end
456
+
457
+ def api_format(format)
458
+ env[Grape::Env::API_FORMAT] = format
470
459
  end
471
460
 
472
461
  def context
@@ -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, **opts.slice(:as))
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, **opts.slice(:as))
165
+ block ? new_scope(orig_attrs, true, &block) : push_declared_params(attrs, opts.slice(:as))
166
166
  end
167
167
  end
168
168
 
@@ -175,19 +175,12 @@ module Grape
175
175
  # end
176
176
  # end
177
177
  def namespace(space = nil, options = {}, &block)
178
- @namespace_description = nil unless instance_variable_defined?(:@namespace_description) && @namespace_description
179
-
180
- if space || block
181
- within_namespace do
182
- previous_namespace_description = @namespace_description
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
178
+ return Namespace.joined_space_path(namespace_stackable(:namespace)) unless space || block
179
+
180
+ within_namespace do
181
+ nest(block) do
182
+ namespace_stackable(:namespace, Namespace.new(space, options)) if space
188
183
  end
189
- else
190
- Namespace.joined_space_path(namespace_stackable(:namespace))
191
184
  end
192
185
  end
193
186