grape 1.7.1 → 2.0.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 +37 -1
- data/CONTRIBUTING.md +1 -1
- data/README.md +30 -25
- data/UPGRADING.md +35 -0
- data/grape.gemspec +3 -6
- data/lib/grape/api.rb +2 -2
- data/lib/grape/content_types.rb +2 -8
- data/lib/grape/dsl/desc.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +11 -11
- data/lib/grape/dsl/request_response.rb +2 -1
- data/lib/grape/dsl/settings.rb +2 -6
- data/lib/grape/endpoint.rb +28 -18
- data/lib/grape/error_formatter/base.rb +1 -1
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/missing_group_type.rb +1 -6
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
- data/lib/grape/exceptions/validation_errors.rb +1 -6
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
- data/lib/grape/extensions/hash.rb +4 -7
- data/lib/grape/extensions/hashie/mash.rb +3 -3
- data/lib/grape/formatter/serializable_hash.rb +7 -7
- data/lib/grape/http/headers.rb +12 -2
- data/lib/grape/middleware/auth/base.rb +1 -1
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/error.rb +5 -5
- data/lib/grape/middleware/formatter.rb +6 -6
- data/lib/grape/middleware/versioner/header.rb +11 -19
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +8 -2
- data/lib/grape/router/route.rb +1 -3
- data/lib/grape/util/lazy_value.rb +3 -11
- data/lib/grape/util/strict_hash_configuration.rb +3 -4
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +8 -2
- data/lib/grape/validations/single_attribute_iterator.rb +3 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
- data/lib/grape/validations/validators/base.rb +9 -20
- data/lib/grape/validations/validators/default_validator.rb +2 -20
- data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
- data/lib/grape/validations/validators/values_validator.rb +14 -5
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +26 -5
- metadata +13 -253
- data/lib/grape/config.rb +0 -34
- data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
- data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
- data/spec/grape/api/custom_validations_spec.rb +0 -256
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -473
- data/spec/grape/api_spec.rb +0 -4347
- data/spec/grape/config_spec.rb +0 -17
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -101
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -535
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -206
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -145
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -21
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -23
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -136
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -40
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -57
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -696
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2029
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4983aa4cc8cb0085312902cb28ced60d0e8ff0762821f50027adec6e66f4f75a
|
4
|
+
data.tar.gz: 1b22ed94c6e526aa8485f4e27ae4cde775ae424018805544620008b090054c7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7680cff51b187ef4f941a8e1596af52ee79b6631da12670e3031eeb79470e2f15a681c3f19406ecdca63e21ad9e2dbcc8362bc4f86c36647940305786f7f082e
|
7
|
+
data.tar.gz: 00dc6bd81800ddaf0638ddc8619a6989f3560b38344807a9058bb470c6ecaa29108e52b9104edafdfb1afd4ee70d98c73a9a51db9a6df9081eb42820a2e25773
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,40 @@
|
|
1
|
-
###
|
1
|
+
### 2.0.0 (2023/11/11)
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
* [#2353](https://github.com/ruby-grape/grape/pull/2353): Added Rails 7.1 support - [@ericproulx](https://github.com/ericproulx).
|
6
|
+
* [#2355](https://github.com/ruby-grape/grape/pull/2355): Set response headers based on Rack version - [@schinery](https://github.com/schinery).
|
7
|
+
* [#2360](https://github.com/ruby-grape/grape/pull/2360): Reduce gem size by removing specs - [@ericproulx](https://github.com/ericproulx).
|
8
|
+
* [#2361](https://github.com/ruby-grape/grape/pull/2361): Remove `Rack::Auth::Digest` - [@ninoseki](https://github.com/ninoseki).
|
9
|
+
|
10
|
+
#### Fixes
|
11
|
+
|
12
|
+
* [#2364](https://github.com/ruby-grape/grape/pull/2364): Add missing requires - [@ericproulx](https://github.com/ericproulx).
|
13
|
+
* [#2366](https://github.com/ruby-grape/grape/pull/2366): Default quality to 1.0 in the `Accept` header when omitted - [@hiddewie](https://github.com/hiddewie).
|
14
|
+
* [#2368](https://github.com/ruby-grape/grape/pull/2368): Stripping the internals of `Grape::Endpoint` when `NoMethodError` is raised - [@jcagarcia](https://github.com/jcagarcia).
|
15
|
+
|
16
|
+
### 1.8.0 (2023/08/30)
|
17
|
+
|
18
|
+
#### Features
|
19
|
+
|
20
|
+
* [#2326](https://github.com/ruby-grape/grape/pull/2326): Use ActiveSupport extensions - [@ericproulx](https://github.com/ericproulx).
|
21
|
+
* [#2327](https://github.com/ruby-grape/grape/pull/2327): Use ActiveSupport deprecation - [@ericproulx](https://github.com/ericproulx).
|
22
|
+
* [#2330](https://github.com/ruby-grape/grape/pull/2330): Use ActiveSupport inflector - [@ericproulx](https://github.com/ericproulx).
|
23
|
+
* [#2331](https://github.com/ruby-grape/grape/pull/2331): Memory optimization when running validators - [@ericproulx](https://github.com/ericproulx).
|
24
|
+
* [#2332](https://github.com/ruby-grape/grape/pull/2332): Use ActiveSupport configurable - [@ericproulx](https://github.com/ericproulx).
|
25
|
+
* [#2333](https://github.com/ruby-grape/grape/pull/2333): Use custom messages in parameter validation with arity 1 - [@thedevjoao](https://github.com/TheDevJoao).
|
26
|
+
* [#2341](https://github.com/ruby-grape/grape/pull/2341): Stop yielding skip value - [@ericproulx](https://github.com/ericproulx).
|
27
|
+
* [#2342](https://github.com/ruby-grape/grape/pull/2342): Allow specifying a handler for grape_exceptions - [@mscrivo](https://github.com/mscrivo).
|
28
|
+
* [#2338](https://github.com/ruby-grape/grape/pull/2338): Fix unknown validator when using requires/optional with entity - [@mscrivo](https://github.com/mscrivo).
|
29
|
+
|
30
|
+
#### Fixes
|
31
|
+
|
32
|
+
* [#2339](https://github.com/ruby-grape/grape/pull/2339): Documentation and specs for remountable configuration in params - [@myxoh](https://github.com/myxoh).
|
33
|
+
* [#2328](https://github.com/ruby-grape/grape/pull/2328): Don't cache Class.instance_methods - [@byroot](https://github.com/byroot).
|
34
|
+
* [#2337](https://github.com/ruby-grape/grape/pull/2337): Fix: allow custom validators that do not end with _validator - [@ericproulx](https://github.com/ericproulx).
|
35
|
+
* [#2346](https://github.com/ruby-grape/grape/pull/2346): Adjust test expectations to conform to rack 3 - [@kbarrette](https://github.com/kbarrette).
|
36
|
+
|
37
|
+
## 1.7.1 (2023/05/14)
|
2
38
|
|
3
39
|
#### Features
|
4
40
|
|
data/CONTRIBUTING.md
CHANGED
@@ -145,7 +145,7 @@ git push origin my-feature-branch -f
|
|
145
145
|
|
146
146
|
#### Check on Your Pull Request
|
147
147
|
|
148
|
-
Go back to your pull request after a few minutes and see whether it passed muster with
|
148
|
+
Go back to your pull request after a few minutes and see whether it passed muster with CI. Everything should look green, otherwise fix issues and amend your commit as described above.
|
149
149
|
|
150
150
|
#### Be Patient
|
151
151
|
|
data/README.md
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
- [Grape for Enterprise](#grape-for-enterprise)
|
16
16
|
- [Installation](#installation)
|
17
17
|
- [Basic Usage](#basic-usage)
|
18
|
+
- [Rails 7.1](#rails-71)
|
18
19
|
- [Mounting](#mounting)
|
19
20
|
- [All](#all)
|
20
21
|
- [Rack](#rack)
|
@@ -114,7 +115,7 @@
|
|
114
115
|
- [Active Model Serializers](#active-model-serializers)
|
115
116
|
- [Sending Raw or No Data](#sending-raw-or-no-data)
|
116
117
|
- [Authentication](#authentication)
|
117
|
-
- [Basic
|
118
|
+
- [Basic Auth](#basic-auth)
|
118
119
|
- [Register custom middleware for authentication](#register-custom-middleware-for-authentication)
|
119
120
|
- [Describing and Inspecting an API](#describing-and-inspecting-an-api)
|
120
121
|
- [Current Route and Endpoint](#current-route-and-endpoint)
|
@@ -159,9 +160,10 @@ content negotiation, versioning and much more.
|
|
159
160
|
|
160
161
|
## Stable Release
|
161
162
|
|
162
|
-
You're reading the documentation for the stable release of Grape,
|
163
|
+
You're reading the documentation for the stable release of Grape, **2.0.0**.
|
163
164
|
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
164
165
|
|
166
|
+
|
165
167
|
## Project Resources
|
166
168
|
|
167
169
|
* [Grape Website](http://www.ruby-grape.org)
|
@@ -177,7 +179,7 @@ The maintainers of Grape are working with Tidelift to deliver commercial support
|
|
177
179
|
|
178
180
|
## Installation
|
179
181
|
|
180
|
-
Ruby 2.
|
182
|
+
Ruby 2.6 or newer is required.
|
181
183
|
|
182
184
|
Grape is available as a gem, to install it run:
|
183
185
|
|
@@ -266,6 +268,10 @@ module Twitter
|
|
266
268
|
end
|
267
269
|
```
|
268
270
|
|
271
|
+
## Rails 7.1
|
272
|
+
|
273
|
+
Grape's [deprecator](https://api.rubyonrails.org/v7.1.0/classes/ActiveSupport/Deprecation.html) will be added to your application's deprecators [automatically](lib/grape/railtie.rb) as `:grape`, so that your application's configuration can be applied to it.
|
274
|
+
|
269
275
|
## Mounting
|
270
276
|
|
271
277
|
### All
|
@@ -524,15 +530,15 @@ end
|
|
524
530
|
```ruby
|
525
531
|
class BasicAPI < Grape::API
|
526
532
|
desc 'Statuses index' do
|
527
|
-
params:
|
533
|
+
params: (configuration[:entity] || API::Entities::Status).documentation
|
528
534
|
end
|
529
535
|
params do
|
530
|
-
requires :all, using:
|
536
|
+
requires :all, using: (configuration[:entity] || API::Entities::Status).documentation
|
531
537
|
end
|
532
538
|
get '/statuses' do
|
533
539
|
statuses = Status.all
|
534
540
|
type = current_user.admin? ? :full : :default
|
535
|
-
present statuses, with:
|
541
|
+
present statuses, with: (configuration[:entity] || API::Entities::Status), type: type
|
536
542
|
end
|
537
543
|
end
|
538
544
|
|
@@ -589,6 +595,10 @@ When an invalid `Accept` header is supplied, a `406 Not Acceptable` error is ret
|
|
589
595
|
option is set to `false`. Otherwise a `404 Not Found` error is returned by Rack if no other route
|
590
596
|
matches.
|
591
597
|
|
598
|
+
Grape will evaluate the relative quality preference included in Accept headers and default to a quality of 1.0 when omitted. In the following example a Grape API that supports XML and JSON in that order will return JSON:
|
599
|
+
|
600
|
+
curl -H "Accept: text/xml;q=0.8, application/json;q=0.9" localhost:1234/resource
|
601
|
+
|
592
602
|
### Accept-Version Header
|
593
603
|
|
594
604
|
```ruby
|
@@ -1593,7 +1603,7 @@ Note endless ranges are also supported with ActiveSupport >= 6.0, but they requi
|
|
1593
1603
|
```ruby
|
1594
1604
|
params do
|
1595
1605
|
requires :minimum, type: Integer, values: 10..
|
1596
|
-
optional :maximum, type: Integer, values: ..10
|
1606
|
+
optional :maximum, type: Integer, values: ..10
|
1597
1607
|
end
|
1598
1608
|
```
|
1599
1609
|
|
@@ -2123,8 +2133,9 @@ curl -H "secret_PassWord: swordfish" ...
|
|
2123
2133
|
|
2124
2134
|
The header name will have been normalized for you.
|
2125
2135
|
|
2126
|
-
- In the `header` helper names will be coerced into a
|
2127
|
-
- In the `
|
2136
|
+
- In the `header` helper names will be coerced into a downcased kebab case as `secret-password` if using Rack 3.
|
2137
|
+
- In the `header` helper names will be coerced into a capitalized kebab case as `Secret-PassWord` if using Rack < 3.
|
2138
|
+
- In the `env` collection they appear in all uppercase, in snake case, and prefixed with 'HTTP_' as `HTTP_SECRET_PASSWORD`
|
2128
2139
|
|
2129
2140
|
The header name will have been normalized per HTTP standards defined in [RFC2616 Section 4.2](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2) regardless of what is being sent by a client.
|
2130
2141
|
|
@@ -2624,6 +2635,14 @@ class Twitter::API < Grape::API
|
|
2624
2635
|
end
|
2625
2636
|
```
|
2626
2637
|
|
2638
|
+
If you want to customize the shape of grape exceptions returned to the user, to match your `:all` handler for example, you can pass a block to `rescue_from :grape_exceptions`.
|
2639
|
+
|
2640
|
+
```ruby
|
2641
|
+
rescue_from :grape_exceptions do |e|
|
2642
|
+
error!(e, e.status)
|
2643
|
+
end
|
2644
|
+
```
|
2645
|
+
|
2627
2646
|
You can also rescue specific exceptions.
|
2628
2647
|
|
2629
2648
|
```ruby
|
@@ -3406,9 +3425,9 @@ end
|
|
3406
3425
|
|
3407
3426
|
## Authentication
|
3408
3427
|
|
3409
|
-
### Basic
|
3428
|
+
### Basic Auth
|
3410
3429
|
|
3411
|
-
Grape has built-in Basic
|
3430
|
+
Grape has built-in Basic authentication (the given `block`
|
3412
3431
|
is executed in the context of the current `Endpoint`). Authentication
|
3413
3432
|
applies to the current namespace and any children, but not parents.
|
3414
3433
|
|
@@ -3419,20 +3438,6 @@ http_basic do |username, password|
|
|
3419
3438
|
end
|
3420
3439
|
```
|
3421
3440
|
|
3422
|
-
Digest auth supports clear-text passwords and password hashes.
|
3423
|
-
|
3424
|
-
```ruby
|
3425
|
-
http_digest({ realm: 'Test Api', opaque: 'app secret' }) do |username|
|
3426
|
-
# lookup the user's password here
|
3427
|
-
end
|
3428
|
-
```
|
3429
|
-
|
3430
|
-
```ruby
|
3431
|
-
http_digest(realm: { realm: 'Test Api', opaque: 'app secret', passwords_hashed: true }) do |username|
|
3432
|
-
# lookup the user's password hash here
|
3433
|
-
end
|
3434
|
-
```
|
3435
|
-
|
3436
3441
|
### Register custom middleware for authentication
|
3437
3442
|
|
3438
3443
|
Grape can use custom Middleware for authentication. How to implement these
|
data/UPGRADING.md
CHANGED
@@ -1,6 +1,41 @@
|
|
1
1
|
Upgrading Grape
|
2
2
|
===============
|
3
3
|
|
4
|
+
### Upgrading to >= 2.0.0
|
5
|
+
|
6
|
+
#### Headers
|
7
|
+
|
8
|
+
As per [rack/rack#1592](https://github.com/rack/rack/issues/1592) Rack 3 is following the HTTP/2+ semantics which require header names to be lower case. To avoid compatibility issues, starting with Grape 1.9.0, headers will be cased based on what version of Rack you are using.
|
9
|
+
|
10
|
+
Given this request:
|
11
|
+
|
12
|
+
```shell
|
13
|
+
curl -H "Content-Type: application/json" -H "Secret-Password: foo" ...
|
14
|
+
```
|
15
|
+
|
16
|
+
If you are using Rack 3 in your application then the headers will be set to:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
{ "content-type" => "application/json", "secret-password" => "foo"}
|
20
|
+
```
|
21
|
+
|
22
|
+
This means if you are checking for header values in your application, you would need to change your code to use downcased keys.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
get do
|
26
|
+
# This would use headers['Secret-Password'] in Rack < 3
|
27
|
+
error!('Unauthorized', 401) unless headers['secret-password'] == 'swordfish'
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
See [#2355](https://github.com/ruby-grape/grape/pull/2355) for more information.
|
32
|
+
|
33
|
+
#### Digest auth deprecation
|
34
|
+
|
35
|
+
Digest auth has been removed along with the deprecation of `Rack::Auth::Digest` in Rack 3.
|
36
|
+
|
37
|
+
See [#2294](https://github.com/ruby-grape/grape/issues/2294) for more information.
|
38
|
+
|
4
39
|
### Upgrading to >= 1.7.0
|
5
40
|
|
6
41
|
#### Exceptions renaming
|
data/grape.gemspec
CHANGED
@@ -20,17 +20,14 @@ Gem::Specification.new do |s|
|
|
20
20
|
'source_code_uri' => "https://github.com/ruby-grape/grape/tree/v#{s.version}"
|
21
21
|
}
|
22
22
|
|
23
|
-
s.add_runtime_dependency 'activesupport'
|
23
|
+
s.add_runtime_dependency 'activesupport', '>= 5'
|
24
24
|
s.add_runtime_dependency 'builder'
|
25
25
|
s.add_runtime_dependency 'dry-types', '>= 1.1'
|
26
26
|
s.add_runtime_dependency 'mustermann-grape', '~> 1.0.0'
|
27
|
-
s.add_runtime_dependency 'rack', '>= 1.3.0'
|
27
|
+
s.add_runtime_dependency 'rack', '>= 1.3.0'
|
28
28
|
s.add_runtime_dependency 'rack-accept'
|
29
29
|
|
30
|
-
s.files
|
31
|
-
s.files += %w[grape.gemspec]
|
32
|
-
s.files += Dir['lib/**/*']
|
33
|
-
s.test_files = Dir['spec/**/*']
|
30
|
+
s.files = Dir['lib/**/*', 'CHANGELOG.md', 'CONTRIBUTING.md', 'README.md', 'grape.png', 'UPGRADING.md', 'LICENSE', 'grape.gemspec']
|
34
31
|
s.require_paths = ['lib']
|
35
32
|
s.required_ruby_version = '>= 2.6.0'
|
36
33
|
end
|
data/lib/grape/api.rb
CHANGED
@@ -8,7 +8,7 @@ module Grape
|
|
8
8
|
# should subclass this class in order to build an API.
|
9
9
|
class API
|
10
10
|
# Class methods that we want to call on the API rather than on the API object
|
11
|
-
NON_OVERRIDABLE =
|
11
|
+
NON_OVERRIDABLE = %i[call call! configuration compile! inherited].freeze
|
12
12
|
|
13
13
|
class Boolean
|
14
14
|
def self.build(val)
|
@@ -50,7 +50,7 @@ module Grape
|
|
50
50
|
|
51
51
|
# Redefines all methods so that are forwarded to add_setup and be recorded
|
52
52
|
def override_all_methods!
|
53
|
-
(base_instance.methods - NON_OVERRIDABLE).each do |method_override|
|
53
|
+
(base_instance.methods - Class.methods - NON_OVERRIDABLE).each do |method_override|
|
54
54
|
define_singleton_method(method_override) do |*args, &block|
|
55
55
|
add_setup(method_override, *args, &block)
|
56
56
|
end
|
data/lib/grape/content_types.rb
CHANGED
@@ -17,17 +17,11 @@ module Grape
|
|
17
17
|
|
18
18
|
class << self
|
19
19
|
def content_types_for_settings(settings)
|
20
|
-
|
21
|
-
|
22
|
-
settings.each_with_object({}) { |value, result| result.merge!(value) }
|
20
|
+
settings&.inject(:merge!)
|
23
21
|
end
|
24
22
|
|
25
23
|
def content_types_for(from_settings)
|
26
|
-
|
27
|
-
from_settings
|
28
|
-
else
|
29
|
-
Grape::ContentTypes::CONTENT_TYPES.merge(default_elements)
|
30
|
-
end
|
24
|
+
from_settings.presence || Grape::ContentTypes::CONTENT_TYPES.merge(default_elements)
|
31
25
|
end
|
32
26
|
end
|
33
27
|
end
|
data/lib/grape/dsl/desc.rb
CHANGED
@@ -68,7 +68,7 @@ module Grape
|
|
68
68
|
end
|
69
69
|
|
70
70
|
config_class.configure(&config_block)
|
71
|
-
warn
|
71
|
+
Grape.deprecator.warn('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') if options.any?
|
72
72
|
options = config_class.settings
|
73
73
|
else
|
74
74
|
options = options.merge(description: description)
|
@@ -103,7 +103,7 @@ module Grape
|
|
103
103
|
|
104
104
|
if type == 'Hash' && !has_children
|
105
105
|
{}
|
106
|
-
elsif type == 'Array' || (type&.start_with?('[') &&
|
106
|
+
elsif type == 'Array' || (type&.start_with?('[') && type&.exclude?(','))
|
107
107
|
[]
|
108
108
|
elsif type == 'Set' || type&.start_with?('#<Set')
|
109
109
|
Set.new
|
@@ -185,7 +185,7 @@ module Grape
|
|
185
185
|
status 302
|
186
186
|
body_message ||= "This resource has been moved temporarily to #{url}."
|
187
187
|
end
|
188
|
-
header
|
188
|
+
header Grape::Http::Headers::LOCATION, url
|
189
189
|
content_type 'text/plain'
|
190
190
|
body body_message
|
191
191
|
end
|
@@ -224,9 +224,9 @@ module Grape
|
|
224
224
|
# Set response content-type
|
225
225
|
def content_type(val = nil)
|
226
226
|
if val
|
227
|
-
header(
|
227
|
+
header(Rack::CONTENT_TYPE, val)
|
228
228
|
else
|
229
|
-
header[
|
229
|
+
header[Rack::CONTENT_TYPE]
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
@@ -280,13 +280,13 @@ module Grape
|
|
280
280
|
# Deprecated method to send files to the client. Use `sendfile` or `stream`
|
281
281
|
def file(value = nil)
|
282
282
|
if value.is_a?(String)
|
283
|
-
warn
|
283
|
+
Grape.deprecator.warn('Use sendfile or stream to send files.')
|
284
284
|
sendfile(value)
|
285
285
|
elsif !value.is_a?(NilClass)
|
286
|
-
warn
|
286
|
+
Grape.deprecator.warn('Use stream to use a Stream object.')
|
287
287
|
stream(value)
|
288
288
|
else
|
289
|
-
warn
|
289
|
+
Grape.deprecator.warn('Use sendfile or stream to send files.')
|
290
290
|
sendfile
|
291
291
|
end
|
292
292
|
end
|
@@ -328,9 +328,9 @@ module Grape
|
|
328
328
|
def stream(value = nil)
|
329
329
|
return if value.nil? && @stream.nil?
|
330
330
|
|
331
|
-
header
|
332
|
-
header
|
333
|
-
header
|
331
|
+
header Rack::CONTENT_LENGTH, nil
|
332
|
+
header Grape::Http::Headers::TRANSFER_ENCODING, nil
|
333
|
+
header Rack::CACHE_CONTROL, 'no-cache' # Skips ETag generation (reading the response up front)
|
334
334
|
if value.is_a?(String)
|
335
335
|
file_body = Grape::ServeStream::FileBody.new(value)
|
336
336
|
@stream = Grape::ServeStream::StreamResponse.new(file_body)
|
@@ -433,7 +433,7 @@ module Grape
|
|
433
433
|
# the given entity_class.
|
434
434
|
def entity_representation_for(entity_class, object, options)
|
435
435
|
embeds = { env: env }
|
436
|
-
embeds[:version] = env[Grape::Env::API_VERSION] if env
|
436
|
+
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
437
437
|
entity_class.represent(object, **embeds.merge(options))
|
438
438
|
end
|
439
439
|
end
|
@@ -112,10 +112,11 @@ module Grape
|
|
112
112
|
|
113
113
|
if args.include?(:all)
|
114
114
|
namespace_inheritable(:rescue_all, true)
|
115
|
-
namespace_inheritable
|
115
|
+
namespace_inheritable(:all_rescue_handler, handler)
|
116
116
|
elsif args.include?(:grape_exceptions)
|
117
117
|
namespace_inheritable(:rescue_all, true)
|
118
118
|
namespace_inheritable(:rescue_grape_exceptions, true)
|
119
|
+
namespace_inheritable(:grape_exceptions_rescue_handler, handler)
|
119
120
|
else
|
120
121
|
handler_type =
|
121
122
|
case options[:rescue_subclasses]
|
data/lib/grape/dsl/settings.rb
CHANGED
@@ -109,13 +109,9 @@ module Grape
|
|
109
109
|
settings = get_or_set :namespace_reverse_stackable, key, nil
|
110
110
|
return if settings.blank?
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
setting.each do |field, value|
|
115
|
-
result[field] ||= value
|
116
|
-
end
|
112
|
+
settings.each_with_object({}) do |setting, result|
|
113
|
+
result.merge!(setting) { |_k, s1, _s2| s1 }
|
117
114
|
end
|
118
|
-
result
|
119
115
|
end
|
120
116
|
|
121
117
|
# (see #unset_global_setting)
|
data/lib/grape/endpoint.rb
CHANGED
@@ -171,10 +171,9 @@ module Grape
|
|
171
171
|
end
|
172
172
|
|
173
173
|
def prepare_routes_requirements
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
base_requirements.merge!(single_requirements)
|
174
|
+
{}.merge!(*namespace_stackable(:namespace).map(&:requirements)).tap do |requirements|
|
175
|
+
endpoint_requirements = options.dig(:route_options, :requirements)
|
176
|
+
requirements.merge!(endpoint_requirements) if endpoint_requirements
|
178
177
|
end
|
179
178
|
end
|
180
179
|
|
@@ -251,7 +250,7 @@ module Grape
|
|
251
250
|
if (allowed_methods = env[Grape::Env::GRAPE_ALLOWED_METHODS])
|
252
251
|
raise Grape::Exceptions::MethodNotAllowed.new(header.merge('Allow' => allowed_methods)) unless options?
|
253
252
|
|
254
|
-
header
|
253
|
+
header Grape::Http::Headers::ALLOW, allowed_methods
|
255
254
|
response_object = ''
|
256
255
|
status 204
|
257
256
|
else
|
@@ -293,7 +292,8 @@ module Grape
|
|
293
292
|
rescue_options: namespace_stackable_with_hash(:rescue_options) || {},
|
294
293
|
rescue_handlers: namespace_reverse_stackable_with_hash(:rescue_handlers) || {},
|
295
294
|
base_only_rescue_handlers: namespace_stackable_with_hash(:base_only_rescue_handlers) || {},
|
296
|
-
all_rescue_handler: namespace_inheritable(:all_rescue_handler)
|
295
|
+
all_rescue_handler: namespace_inheritable(:all_rescue_handler),
|
296
|
+
grape_exceptions_rescue_handler: namespace_inheritable(:grape_exceptions_rescue_handler)
|
297
297
|
|
298
298
|
stack.concat namespace_stackable(:middleware)
|
299
299
|
|
@@ -318,8 +318,8 @@ module Grape
|
|
318
318
|
end
|
319
319
|
|
320
320
|
def build_helpers
|
321
|
-
helpers = namespace_stackable(:helpers)
|
322
|
-
Module.new { helpers
|
321
|
+
helpers = namespace_stackable(:helpers)
|
322
|
+
Module.new { helpers&.each { |mod_to_include| include mod_to_include } }
|
323
323
|
end
|
324
324
|
|
325
325
|
private :build_stack, :build_helpers
|
@@ -345,11 +345,9 @@ module Grape
|
|
345
345
|
end
|
346
346
|
end
|
347
347
|
|
348
|
-
def run_validators(
|
348
|
+
def run_validators(validators, request)
|
349
349
|
validation_errors = []
|
350
350
|
|
351
|
-
validators = validator_factories.map { |options| Grape::Validations::ValidatorFactory.create_validator(**options) }
|
352
|
-
|
353
351
|
ActiveSupport::Notifications.instrument('endpoint_run_validators.grape', endpoint: self, validators: validators, request: request) do
|
354
352
|
validators.each do |validator|
|
355
353
|
validator.validate(request)
|
@@ -367,39 +365,51 @@ module Grape
|
|
367
365
|
|
368
366
|
def run_filters(filters, type = :other)
|
369
367
|
ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', endpoint: self, filters: filters, type: type) do
|
370
|
-
|
368
|
+
filters&.each { |filter| instance_eval(&filter) }
|
371
369
|
end
|
372
370
|
post_extension = DSL::InsideRoute.post_filter_methods(type)
|
373
371
|
extend post_extension if post_extension
|
374
372
|
end
|
375
373
|
|
376
374
|
def befores
|
377
|
-
namespace_stackable(:befores)
|
375
|
+
namespace_stackable(:befores)
|
378
376
|
end
|
379
377
|
|
380
378
|
def before_validations
|
381
|
-
namespace_stackable(:before_validations)
|
379
|
+
namespace_stackable(:before_validations)
|
382
380
|
end
|
383
381
|
|
384
382
|
def after_validations
|
385
|
-
namespace_stackable(:after_validations)
|
383
|
+
namespace_stackable(:after_validations)
|
386
384
|
end
|
387
385
|
|
388
386
|
def afters
|
389
|
-
namespace_stackable(:afters)
|
387
|
+
namespace_stackable(:afters)
|
390
388
|
end
|
391
389
|
|
392
390
|
def finallies
|
393
|
-
namespace_stackable(:finallies)
|
391
|
+
namespace_stackable(:finallies)
|
394
392
|
end
|
395
393
|
|
396
394
|
def validations
|
397
|
-
|
395
|
+
return enum_for(:validations) unless block_given?
|
396
|
+
|
397
|
+
route_setting(:saved_validations)&.each do |saved_validation|
|
398
|
+
yield Grape::Validations::ValidatorFactory.create_validator(**saved_validation)
|
399
|
+
end
|
398
400
|
end
|
399
401
|
|
400
402
|
def options?
|
401
403
|
options[:options_route_enabled] &&
|
402
404
|
env[Grape::Http::Headers::REQUEST_METHOD] == Grape::Http::Headers::OPTIONS
|
403
405
|
end
|
406
|
+
|
407
|
+
def method_missing(name, *_args)
|
408
|
+
raise NoMethodError.new("undefined method `#{name}' for #{self.class} in `#{route.origin}' endpoint")
|
409
|
+
end
|
410
|
+
|
411
|
+
def respond_to_missing?(method_name, include_private = false)
|
412
|
+
super
|
413
|
+
end
|
404
414
|
end
|
405
415
|
end
|
@@ -27,7 +27,7 @@ module Grape
|
|
27
27
|
|
28
28
|
if presenter
|
29
29
|
embeds = { env: env }
|
30
|
-
embeds[:version] = env[Grape::Env::API_VERSION] if env
|
30
|
+
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
31
31
|
presented_message = presenter.represent(presented_message, embeds).serializable_hash
|
32
32
|
end
|
33
33
|
|
@@ -73,11 +73,11 @@ module Grape
|
|
73
73
|
options = options.dup
|
74
74
|
options[:default] &&= options[:default].to_s
|
75
75
|
message = ::I18n.translate(key, **options)
|
76
|
-
message.
|
76
|
+
message.presence || fallback_message(key, **options)
|
77
77
|
end
|
78
78
|
|
79
79
|
def fallback_message(key, **options)
|
80
|
-
if ::I18n.enforce_available_locales &&
|
80
|
+
if ::I18n.enforce_available_locales && ::I18n.available_locales.exclude?(FALLBACK_LOCALE)
|
81
81
|
key
|
82
82
|
else
|
83
83
|
::I18n.translate(key, locale: FALLBACK_LOCALE, **options)
|
@@ -10,9 +10,4 @@ module Grape
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
Grape::Exceptions::MissingGroupTypeError =
|
14
|
-
def initialize(*)
|
15
|
-
super
|
16
|
-
warn '[DEPRECATION] `Grape::Exceptions::MissingGroupTypeError` is deprecated. Use `Grape::Exceptions::MissingGroupType` instead.'
|
17
|
-
end
|
18
|
-
end
|
13
|
+
Grape::Exceptions::MissingGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::MissingGroupTypeError', 'Grape::Exceptions::MissingGroupType', Grape.deprecator)
|
@@ -10,9 +10,4 @@ module Grape
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
Grape::Exceptions::UnsupportedGroupTypeError =
|
14
|
-
def initialize(*)
|
15
|
-
super
|
16
|
-
warn '[DEPRECATION] `Grape::Exceptions::UnsupportedGroupTypeError` is deprecated. Use `Grape::Exceptions::UnsupportedGroupType` instead.'
|
17
|
-
end
|
18
|
-
end
|
13
|
+
Grape::Exceptions::UnsupportedGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::UnsupportedGroupTypeError', 'Grape::Exceptions::UnsupportedGroupType', Grape.deprecator)
|
@@ -13,12 +13,7 @@ module Grape
|
|
13
13
|
attr_reader :errors
|
14
14
|
|
15
15
|
def initialize(errors: [], headers: {}, **_options)
|
16
|
-
@errors =
|
17
|
-
errors.each do |validation_error|
|
18
|
-
@errors[validation_error.params] ||= []
|
19
|
-
@errors[validation_error.params] << validation_error
|
20
|
-
end
|
21
|
-
|
16
|
+
@errors = errors.group_by(&:params)
|
22
17
|
super message: full_messages.join(', '), status: 400, headers: headers
|
23
18
|
end
|
24
19
|
|
@@ -16,9 +16,9 @@ module Grape
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def build_params
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
::ActiveSupport::HashWithIndifferentAccess.new(rack_params).tap do |params|
|
20
|
+
params.deep_merge!(grape_routing_args) if env.key?(Grape::Env::GRAPE_ROUTING_ARGS)
|
21
|
+
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -11,13 +11,10 @@ module Grape
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def build_params
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def post_process_params(params)
|
20
|
-
Grape::Extensions::DeepSymbolizeHash.deep_symbolize_keys_in(params)
|
14
|
+
rack_params.deep_dup.tap do |params|
|
15
|
+
params.deep_merge!(grape_routing_args) if env.key?(Grape::Env::GRAPE_ROUTING_ARGS)
|
16
|
+
params.deep_symbolize_keys!
|
17
|
+
end
|
21
18
|
end
|
22
19
|
end
|
23
20
|
end
|
@@ -15,9 +15,9 @@ module Grape
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def build_params
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
::Hashie::Mash.new(rack_params).tap do |params|
|
19
|
+
params.deep_merge!(grape_routing_args) if env.key?(Grape::Env::GRAPE_ROUTING_ARGS)
|
20
|
+
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|