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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83e82bddb3698a0f659d7c58edcb20c2d7edd44cce6e78f31139a2cf3452da0e
|
4
|
+
data.tar.gz: d47076d4e1b7445029b7695b5cfcb0ddebf72a1106743817eb583f79e636c8fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a22fbee812a61d12aa8ca151cc53835df146d840173fc92d9bb4ae049b5b14a70f6d399fcd06440167312af7bd60116e8382f21424a7c8b494b0251a82e7cea5
|
7
|
+
data.tar.gz: cd3d6d737305696db1cb703639dcdc3d7a6a4e32c02a25fd3942bef3e91529a8acaf11bb5cd4039b108ef2c908461c233a54207d2c4f528959fd944afeac0b22
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,58 @@
|
|
1
|
+
### 2.4.0 (2025-06-18)
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
* [#2532](https://github.com/ruby-grape/grape/pull/2532): Update RuboCop 1.71.2 - [@ericproulx](https://github.com/ericproulx).
|
6
|
+
* [#2535](https://github.com/ruby-grape/grape/pull/2535): Delegate calls to inner objects - [@ericproulx](https://github.com/ericproulx).
|
7
|
+
* [#2537](https://github.com/ruby-grape/grape/pull/2537): Use activesupport `try` pattern - [@ericproulx](https://github.com/ericproulx).
|
8
|
+
* [#2536](https://github.com/ruby-grape/grape/pull/2536): Update normalize_path like Rails - [@ericproulx](https://github.com/ericproulx).
|
9
|
+
* [#2540](https://github.com/ruby-grape/grape/pull/2540): Introduce params builder with symbolized short name - [@ericproulx](https://github.com/ericproulx).
|
10
|
+
* [#2550](https://github.com/ruby-grape/grape/pull/2550): Drop ActiveSupport 6.0 - [@ericproulx](https://github.com/ericproulx).
|
11
|
+
* [#2549](https://github.com/ruby-grape/grape/pull/2549): Delegate cookies management to `Grape::Request` - [@ericproulx](https://github.com/ericproulx).
|
12
|
+
* [#2554](https://github.com/ruby-grape/grape/pull/2554): Remove `Grape::Http::Headers` and `Grape::Util::Lazy::Object` - [@ericproulx](https://github.com/ericproulx).
|
13
|
+
* [#2556](https://github.com/ruby-grape/grape/pull/2556): Remove unused `Grape::Request::DEFAULT_PARAMS_BUILDER` constant - [@eriklovmo](https://github.com/eriklovmo).
|
14
|
+
* [#2558](https://github.com/ruby-grape/grape/pull/2558): Add Ruby's option `enable_frozen_string_literal` in CI - [@ericproulx](https://github.com/ericproulx).
|
15
|
+
* [#2557](https://github.com/ruby-grape/grape/pull/2557): Add `lint!` - [@ericproulx](https://github.com/ericproulx).
|
16
|
+
* [#2561](https://github.com/ruby-grape/grape/pull/2561): Optimize hash alloc for middleware's default options - [@ericproulx](https://github.com/ericproulx).
|
17
|
+
* [#2563](https://github.com/ruby-grape/grape/pull/2563): Update `Grape::Middleware::Auth::Base` - [@ericproulx](https://github.com/ericproulx).
|
18
|
+
* [#2571](https://github.com/ruby-grape/grape/pull/2571): Update RuboCop 1.75.8 - [@pieterocp](https://github.com/pieterocp).
|
19
|
+
|
20
|
+
#### Fixes
|
21
|
+
|
22
|
+
* [#2538](https://github.com/ruby-grape/grape/pull/2538): Fix validating nested json array params - [@mohammednasser-32](https://github.com/mohammednasser-32).
|
23
|
+
* [#2543](https://github.com/ruby-grape/grape/pull/2543): Fix array allocation on mount - [@ericproulx](https://github.com/ericproulx).
|
24
|
+
* [#2546](https://github.com/ruby-grape/grape/pull/2546): Fix middleware with keywords - [@ericproulx](https://github.com/ericproulx).
|
25
|
+
* [#2547](https://github.com/ruby-grape/grape/pull/2547): Remove jsonapi related code - [@ericproulx](https://github.com/ericproulx).
|
26
|
+
* [#2548](https://github.com/ruby-grape/grape/pull/2548): Formatting from header acts like versioning from header - [@ericproulx](https://github.com/ericproulx).
|
27
|
+
* [#2552](https://github.com/ruby-grape/grape/pull/2552): Fix declared params optional array - [@ericproulx](https://github.com/ericproulx).
|
28
|
+
* [#2553](https://github.com/ruby-grape/grape/pull/2553): Improve performance of query params parsing - [@ericproulx](https://github.com/ericproulx).
|
29
|
+
|
30
|
+
### 2.3.0 (2025-02-08)
|
31
|
+
|
32
|
+
#### Features
|
33
|
+
|
34
|
+
* [#2497](https://github.com/ruby-grape/grape/pull/2497): Update RuboCop to 1.66.1 - [@ericproulx](https://github.com/ericproulx).
|
35
|
+
* [#2500](https://github.com/ruby-grape/grape/pull/2500): Remove deprecated `file` method - [@ericproulx](https://github.com/ericproulx).
|
36
|
+
* [#2501](https://github.com/ruby-grape/grape/pull/2501): Remove deprecated `except` and `proc` options in values validator - [@ericproulx](https://github.com/ericproulx).
|
37
|
+
* [#2502](https://github.com/ruby-grape/grape/pull/2502): Remove deprecation `options` in `desc` - [@ericproulx](https://github.com/ericproulx).
|
38
|
+
* [#2512](https://github.com/ruby-grape/grape/pull/2512): Optimize hash alloc - [@ericproulx](https://github.com/ericproulx).
|
39
|
+
* [#2513](https://github.com/ruby-grape/grape/pull/2513): Optimize Grape::Path - [@ericproulx](https://github.com/ericproulx).
|
40
|
+
* [#2514](https://github.com/ruby-grape/grape/pull/2514): Add rails 8.0 to CI - [@ericproulx](https://github.com/ericproulx).
|
41
|
+
* [#2516](https://github.com/ruby-grape/grape/pull/2516): Dynamic registration for parsers, formatters, versioners - [@ericproulx](https://github.com/ericproulx).
|
42
|
+
* [#2518](https://github.com/ruby-grape/grape/pull/2518): Add ruby 3.4 to CI - [@ericproulx](https://github.com/ericproulx).
|
43
|
+
|
44
|
+
#### Fixes
|
45
|
+
|
46
|
+
* [#2504](https://github.com/ruby-grape/grape/pull/2504): Fix leaky modules in specs - [@ericproulx](https://github.com/ericproulx).
|
47
|
+
* [#2506](https://github.com/ruby-grape/grape/pull/2506): Fix fetch_formatter api_format - [@ericproulx](https://github.com/ericproulx).
|
48
|
+
* [#2507](https://github.com/ruby-grape/grape/pull/2507): Fix type: Set with values - [@nikolai-b](https://github.com/nikolai-b).
|
49
|
+
* [#2510](https://github.com/ruby-grape/grape/pull/2510): Fix ContractScope's validator inheritance - [@ericproulx](https://github.com/ericproulx).
|
50
|
+
* [#2521](https://github.com/ruby-grape/grape/pull/2521): Fixed typo in README - [@datpmt](https://github.com/datpmt).
|
51
|
+
* [#2525](https://github.com/ruby-grape/grape/pull/2525): Require logger before active_support - [@ericproulx](https://github.com/ericproulx).
|
52
|
+
* [#2524](https://github.com/ruby-grape/grape/pull/2524): Fix validators bad encoding - [@ericproulx](https://github.com/ericproulx).
|
53
|
+
* [#2530](https://github.com/ruby-grape/grape/pull/2530): Fix endpoint's status when rescue_from without a block - [@ericproulx](https://github.com/ericproulx).
|
54
|
+
* [#2529](https://github.com/ruby-grape/grape/pull/2529): Fix missing settings on mounted routes (when settings are identical) - [@Haerezis](https://github.com/Haerezis).
|
55
|
+
|
1
56
|
### 2.2.0 (2024-09-14)
|
2
57
|
|
3
58
|
#### Features
|
data/CONTRIBUTING.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Contributing to Grape
|
2
2
|
=====================
|
3
3
|
|
4
|
-
Grape is work of [hundreds of contributors](https://github.com/ruby-grape/grape/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/ruby-grape/grape/pulls), [propose features and discuss issues](https://github.com/ruby-grape/grape/issues).
|
4
|
+
Grape is work of [hundreds of contributors](https://github.com/ruby-grape/grape/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/ruby-grape/grape/pulls), [propose features and discuss issues](https://github.com/ruby-grape/grape/issues).
|
5
5
|
|
6
6
|
#### Fork the Project
|
7
7
|
|
data/README.md
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|

|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/grape)
|
4
|
-
[](https://codeclimate.com/github/ruby-grape/grape)
|
4
|
+
[](https://github.com/ruby-grape/grape/actions/workflows/test.yml)
|
6
5
|
[](https://coveralls.io/github/ruby-grape/grape?branch=master)
|
7
|
-
[](https://inch-ci.org/github/ruby-grape/grape)
|
8
|
-
[](https://gitter.im/ruby-grape/grape?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
9
6
|
|
10
7
|
## Table of Contents
|
11
8
|
|
@@ -31,6 +28,8 @@
|
|
31
28
|
- [Header](#header)
|
32
29
|
- [Accept-Version Header](#accept-version-header)
|
33
30
|
- [Param](#param)
|
31
|
+
- [Linting](#linting)
|
32
|
+
- [Bug in Rack::ETag under Rack 3.X](#bug-in-racketag-under-rack-3x)
|
34
33
|
- [Describing Methods](#describing-methods)
|
35
34
|
- [Configuration](#configuration)
|
36
35
|
- [Parameters](#parameters)
|
@@ -157,13 +156,14 @@ Grape is a REST-like API framework for Ruby. It's designed to run on Rack or com
|
|
157
156
|
|
158
157
|
## Stable Release
|
159
158
|
|
160
|
-
You're reading the documentation for the stable release of Grape, 2.
|
159
|
+
You're reading the documentation for the stable release of Grape, 2.4.0.
|
160
|
+
Please read [UPGRADING](https://github.com/ruby-grape/grape/blob/v2.4.0/UPGRADING.md) when upgrading from a previous version.
|
161
161
|
|
162
162
|
## Project Resources
|
163
163
|
|
164
164
|
* [Grape Website](http://www.ruby-grape.org)
|
165
165
|
* [Documentation](http://www.rubydoc.info/gems/grape)
|
166
|
-
* Need help?
|
166
|
+
* Need help? [Open an Issue](https://github.com/ruby-grape/grape/issues)
|
167
167
|
* [Follow us on Twitter](https://twitter.com/grapeframework)
|
168
168
|
|
169
169
|
## Grape for Enterprise
|
@@ -271,7 +271,7 @@ Grape's [deprecator](https://api.rubyonrails.org/v7.1.0/classes/ActiveSupport/De
|
|
271
271
|
### All
|
272
272
|
|
273
273
|
|
274
|
-
By default Grape will compile the routes on the first route, it is possible to pre-load routes using the `compile!` method.
|
274
|
+
By default Grape will compile the routes on the first route, but it is possible to pre-load routes using the `compile!` method.
|
275
275
|
|
276
276
|
```ruby
|
277
277
|
Twitter::API.compile!
|
@@ -652,6 +652,27 @@ version 'v1', using: :param, parameter: 'v'
|
|
652
652
|
curl http://localhost:9292/statuses/public_timeline?v=v1
|
653
653
|
|
654
654
|
|
655
|
+
## Linting
|
656
|
+
|
657
|
+
You can check whether your API is in conformance with the [Rack's specification](https://github.com/rack/rack/blob/main/SPEC.rdoc) by calling `lint!` at the API level or through [configuration](#configuration).
|
658
|
+
|
659
|
+
```ruby
|
660
|
+
class Api < Grape::API
|
661
|
+
lint!
|
662
|
+
end
|
663
|
+
```
|
664
|
+
```ruby
|
665
|
+
Grape.configure do |config|
|
666
|
+
config.lint = true
|
667
|
+
end
|
668
|
+
```
|
669
|
+
```ruby
|
670
|
+
Grape.config.lint = true
|
671
|
+
```
|
672
|
+
|
673
|
+
### Bug in Rack::ETag under Rack 3.X
|
674
|
+
If you're using Rack 3.X and the `Rack::Etag` middleware (used by [Rails](https://guides.rubyonrails.org/rails_on_rack.html#inspecting-middleware-stack)), a [bug](https://github.com/rack/rack/pull/2324) related to linting has been fixed in [3.1.13](https://github.com/rack/rack/blob/v3.1.13/CHANGELOG.md#3113---2025-04-13) and [3.0.15](https://github.com/rack/rack/blob/v3.1.13/CHANGELOG.md#3015---2025-04-13) respectively.
|
675
|
+
|
655
676
|
## Describing Methods
|
656
677
|
|
657
678
|
You can add a description to API methods and namespaces. The description would be used by [grape-swagger][grape-swagger] to generate swagger compliant documentation.
|
@@ -718,10 +739,13 @@ For example, for the `param_builder`, the following code could run in an initial
|
|
718
739
|
|
719
740
|
```ruby
|
720
741
|
Grape.configure do |config|
|
721
|
-
config.param_builder =
|
742
|
+
config.param_builder = :hashie_mash
|
722
743
|
end
|
723
744
|
```
|
724
745
|
|
746
|
+
Available parameter builders are `:hash`, `:hash_with_indifferent_access`, and `:hashie_mash`.
|
747
|
+
See [params_builder](lib/grape/params_builder).
|
748
|
+
|
725
749
|
You can also configure a single API:
|
726
750
|
|
727
751
|
```ruby
|
@@ -788,7 +812,7 @@ By default parameters are available as `ActiveSupport::HashWithIndifferentAccess
|
|
788
812
|
|
789
813
|
```ruby
|
790
814
|
class API < Grape::API
|
791
|
-
|
815
|
+
build_with :hashie_mash
|
792
816
|
|
793
817
|
params do
|
794
818
|
optional :color, type: String
|
@@ -802,16 +826,15 @@ The class can also be overridden on individual parameter blocks using `build_wit
|
|
802
826
|
|
803
827
|
```ruby
|
804
828
|
params do
|
805
|
-
build_with
|
829
|
+
build_with :hash
|
806
830
|
optional :color, type: String
|
807
831
|
end
|
808
832
|
```
|
809
833
|
|
810
|
-
Or globally with the [Configuration](#configuration) `Grape.configure.param_builder`.
|
811
|
-
|
812
834
|
In the example above, `params["color"]` will return `nil` since `params` is a plain `Hash`.
|
813
835
|
|
814
|
-
Available parameter builders are
|
836
|
+
Available parameter builders are `:hash`, `:hash_with_indifferent_access`, and `:hashie_mash`.
|
837
|
+
See [params_builder](lib/grape/params_builder).
|
815
838
|
|
816
839
|
### Declared
|
817
840
|
|
@@ -2045,7 +2068,7 @@ end
|
|
2045
2068
|
```ruby
|
2046
2069
|
params do
|
2047
2070
|
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
|
2071
|
+
requires :str, type: String, length: { min: 5, message: 'str is expected to be at least 5 characters long' }
|
2049
2072
|
requires :list, type: [Integer], length: { min: 2, max: 3, message: 'list is expected to have between 2 and 3 elements' }
|
2050
2073
|
end
|
2051
2074
|
```
|
@@ -3065,7 +3088,7 @@ end
|
|
3065
3088
|
* `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
3089
|
* `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
3090
|
|
3068
|
-
You can override this process explicitly by
|
3091
|
+
You can override this process explicitly by calling `api_format` in the API itself.
|
3069
3092
|
For example, the following API will let you upload arbitrary files and return their contents as an attachment with the correct MIME type.
|
3070
3093
|
|
3071
3094
|
```ruby
|
@@ -3073,7 +3096,7 @@ class Twitter::API < Grape::API
|
|
3073
3096
|
post 'attachment' do
|
3074
3097
|
filename = params[:file][:filename]
|
3075
3098
|
content_type MIME::Types.type_for(filename)[0].to_s
|
3076
|
-
|
3099
|
+
api_format :binary # there's no formatter for :binary, data will be returned "as is"
|
3077
3100
|
header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(filename)}"
|
3078
3101
|
params[:file][:tempfile].read
|
3079
3102
|
end
|
@@ -3535,8 +3558,8 @@ Please use `Route#xyz` instead.
|
|
3535
3558
|
|
3536
3559
|
Note that difference of `Route#options` and `Route#settings`.
|
3537
3560
|
|
3538
|
-
The `options` can be referred from your route, it should be set by
|
3539
|
-
The `settings` can also be referred from your route, but it should be set by
|
3561
|
+
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`.
|
3562
|
+
The `settings` can also be referred from your route, but it should be set by specifying key and value on `route_setting`.
|
3540
3563
|
|
3541
3564
|
## Current Route and Endpoint
|
3542
3565
|
|
data/UPGRADING.md
CHANGED
@@ -1,6 +1,80 @@
|
|
1
1
|
Upgrading Grape
|
2
2
|
===============
|
3
3
|
|
4
|
+
### Upgrading to >= 2.4.0
|
5
|
+
|
6
|
+
#### Grape::Middleware::Auth::Base
|
7
|
+
`type` is now validated at compile time and will raise a `Grape::Exceptions::UnknownAuthStrategy` if unknown.
|
8
|
+
|
9
|
+
#### Grape::Middleware::Base
|
10
|
+
|
11
|
+
- Second argument `options` is now a double splat (**) instead of single splat (*). If you're redefining `initialize` in your middleware and/or calling `super` in it, you might have to adapt the signature and the `super` call. Also, you might have to remove `{}` if you're pass `options` as a literal `Hash` or add `**` if you're using a variable.
|
12
|
+
- `Grape::Middleware::Helpers` has been removed. The equivalent method `context` is now part of `Grape::Middleware::Base`.
|
13
|
+
|
14
|
+
#### Grape::Http::Headers, Grape::Util::Lazy::Object
|
15
|
+
|
16
|
+
Both have been removed. See [2554](https://github.com/ruby-grape/grape/pull/2554).
|
17
|
+
Here are the notable changes:
|
18
|
+
|
19
|
+
- Constants like `HTTP_ACCEPT` have been replaced by their literal value.
|
20
|
+
- `SUPPORTED_METHODS` has been moved to `Grape` module.
|
21
|
+
- `HTTP_HEADERS` has been moved to `Grape::Request` and renamed `KNOWN_HEADERS`. The last has been refreshed with new headers, and it's not lazy anymore.
|
22
|
+
- `SUPPORTED_METHODS_WITHOUT_OPTIONS` and `find_supported_method` have been removed.
|
23
|
+
|
24
|
+
#### Grape::Middleware::Base
|
25
|
+
|
26
|
+
- Constant `TEXT_HTML` has been removed in favor of using literal string 'text/html'.
|
27
|
+
- `rack_request` and `query_params` have been added. Feel free to call these in your middlewares.
|
28
|
+
|
29
|
+
#### Params Builder
|
30
|
+
|
31
|
+
- Passing a class to `build_with` or `Grape.config.param_builder` has been deprecated in favor of a symbolized short_name. See `SHORTNAME_LOOKUP` in [params_builder](lib/grape/params_builder.rb).
|
32
|
+
- Including Grape's extensions like `Grape::Extensions::Hashie::Mash::ParamBuilder` has been deprecated in favor of using `build_with` at the route level.
|
33
|
+
|
34
|
+
#### Accept Header Negotiation Harmonized
|
35
|
+
|
36
|
+
[Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept) header is now fully interpreted through `Rack::Utils.best_q_match` which is following [RFC2616 14.1](https://datatracker.ietf.org/doc/html/rfc2616#section-14.1). Since [Grape 2.1.0](https://github.com/ruby-grape/grape/blob/master/CHANGELOG.md#210-20240615), the [header versioning strategy](https://github.com/ruby-grape/grape?tab=readme-ov-file#header) was adhering to it, but `Grape::Middleware::Formatter` never did.
|
37
|
+
|
38
|
+
Your API might act differently since it will strictly follow the [RFC2616 14.1](https://datatracker.ietf.org/doc/html/rfc2616#section-14.1) when interpreting the `Accept` header. Here are the differences:
|
39
|
+
|
40
|
+
##### Invalid or missing quality ranking
|
41
|
+
The following used to yield `application/xml` and now will yield `application/json` as the preferred media type:
|
42
|
+
- `application/json;q=invalid,application/xml;q=0.5`
|
43
|
+
- `application/json,application/xml;q=1.0`
|
44
|
+
|
45
|
+
For the invalid case, the value `invalid` was automatically `to_f` and `invalid.to_f` equals `0.0`. Now, since it doesn't match [Rack's regex](https://github.com/rack/rack/blob/3-1-stable/lib/rack/utils.rb#L138), its interpreted as non provided and its quality ranking equals 1.0.
|
46
|
+
|
47
|
+
For the non provided case, 1.0 was automatically assigned and in a case of multiple best matches, the first was returned based on Ruby's sort_by `quality`. Now, 1.0 is still assigned and the last is returned in case of multiple best matches. See [Rack's implementation](https://github.com/rack/rack/blob/e8f47608668d507e0f231a932fa37c9ca551c0a5/lib/rack/utils.rb#L167) of the RFC.
|
48
|
+
|
49
|
+
##### Considering the closest generic when vendor tree
|
50
|
+
Excluding the [header versioning strategy](https://github.com/ruby-grape/grape?tab=readme-ov-file#header), whenever a media type with the [vendor tree](https://datatracker.ietf.org/doc/html/rfc6838#section-3.2) leading facet `vnd.` like `application/vnd.api+json` was provided, Grape would also consider its closest generic when negotiating. In that case, `application/json` was added to the negotiation. Now, it will just consider the provided media types without considering any closest generics, and you'll need to [register](https://github.com/ruby-grape/grape?tab=readme-ov-file#api-formats) it.
|
51
|
+
You can find the official vendor tree registrations on [IANA](https://www.iana.org/assignments/media-types/media-types.xhtml)
|
52
|
+
|
53
|
+
#### Custom Validators
|
54
|
+
|
55
|
+
If you now receive an error of `'Grape::Validations.require_validator': unknown validator: your_custom_validation (Grape::Exceptions::UnknownValidator)` after upgrading to 2.4.0 then you will need to ensure that you require the `your_custom_validation` file before your Grape API code is loaded.
|
56
|
+
|
57
|
+
See [2533](https://github.com/ruby-grape/grape/issues/2533) for more information.
|
58
|
+
|
59
|
+
### Upgrading to >= 2.3.0
|
60
|
+
|
61
|
+
### `content_type` vs `api.format` inside API
|
62
|
+
|
63
|
+
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.
|
64
|
+
In addition, the function `api_format` has been added. Instead of setting `env['api.format']` directly, you can call `api_format`.
|
65
|
+
See [#2506](https://github.com/ruby-grape/grape/pull/2506) for more information.
|
66
|
+
|
67
|
+
#### Remove Deprecated Methods and Options
|
68
|
+
|
69
|
+
- Deprecated `file` method has been removed. Use `send_file` or `stream`.
|
70
|
+
See [#2500](https://github.com/ruby-grape/grape/pull/2500) for more information.
|
71
|
+
|
72
|
+
- The `except` and `proc` options have been removed from the `values` validator. Use `except_values` validator or assign `proc` directly to `values`.
|
73
|
+
See [#2501](https://github.com/ruby-grape/grape/pull/2501) for more information.
|
74
|
+
|
75
|
+
- `Passing an options hash and a block to 'desc'` deprecation has been removed. Move all hash options to block instead.
|
76
|
+
See [#2502](https://github.com/ruby-grape/grape/pull/2502) for more information.
|
77
|
+
|
4
78
|
### Upgrading to >= 2.2.0
|
5
79
|
|
6
80
|
### `Length` validator
|
@@ -64,7 +138,7 @@ When using together with `Grape::Extensions::Hash::ParamBuilder`, `route_param`
|
|
64
138
|
This was a regression introduced by [#2326](https://github.com/ruby-grape/grape/pull/2326) in Grape v1.8.0.
|
65
139
|
|
66
140
|
```ruby
|
67
|
-
|
141
|
+
Grape.configure do |config|
|
68
142
|
config.param_builder = Grape::Extensions::Hash::ParamBuilder
|
69
143
|
end
|
70
144
|
|
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.
|
25
|
-
s.
|
26
|
-
s.
|
27
|
-
s.
|
28
|
-
s.
|
24
|
+
s.add_dependency 'activesupport', '>= 6.1'
|
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']
|
data/lib/grape/api/instance.rb
CHANGED
@@ -5,6 +5,7 @@ module Grape
|
|
5
5
|
# The API Instance class, is the engine behind Grape::API. Each class that inherits
|
6
6
|
# from this will represent a different API instance
|
7
7
|
class Instance
|
8
|
+
extend Grape::Middleware::Auth::DSL
|
8
9
|
include Grape::DSL::API
|
9
10
|
|
10
11
|
class << self
|
@@ -112,7 +113,7 @@ module Grape
|
|
112
113
|
def evaluate_as_instance_with_configuration(block, lazy: false)
|
113
114
|
lazy_block = Grape::Util::Lazy::Block.new do |configuration|
|
114
115
|
value_for_configuration = configuration
|
115
|
-
self.configuration = value_for_configuration.evaluate if value_for_configuration.
|
116
|
+
self.configuration = value_for_configuration.evaluate if value_for_configuration.try(:lazy?)
|
116
117
|
response = instance_eval(&block)
|
117
118
|
self.configuration = value_for_configuration
|
118
119
|
response
|
@@ -164,7 +165,7 @@ module Grape
|
|
164
165
|
status, headers, response = @router.call(env)
|
165
166
|
unless cascade?
|
166
167
|
headers = Grape::Util::Header.new.merge(headers)
|
167
|
-
headers.delete(
|
168
|
+
headers.delete('X-Cascade')
|
168
169
|
end
|
169
170
|
|
170
171
|
[status, headers, response]
|
@@ -194,88 +195,52 @@ module Grape
|
|
194
195
|
# will return an HTTP 405 response for any HTTP method that the resource
|
195
196
|
# cannot handle.
|
196
197
|
def add_head_not_allowed_methods_and_options_methods
|
197
|
-
versioned_route_configs = collect_route_config_per_pattern
|
198
198
|
# The paths we collected are prepared (cf. Path#prepare), so they
|
199
199
|
# contain already versioning information when using path versioning.
|
200
|
+
all_routes = self.class.endpoints.map(&:routes).flatten
|
201
|
+
|
200
202
|
# Disable versioning so adding a route won't prepend versioning
|
201
203
|
# informations again.
|
202
|
-
|
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
|
204
|
+
without_root_prefix_and_versioning { collect_route_config_per_pattern(all_routes) }
|
220
205
|
end
|
221
206
|
|
222
|
-
def collect_route_config_per_pattern
|
223
|
-
all_routes = self.class.endpoints.map(&:routes).flatten
|
207
|
+
def collect_route_config_per_pattern(all_routes)
|
224
208
|
routes_by_regexp = all_routes.group_by(&:pattern_regexp)
|
225
209
|
|
226
210
|
# Build the configuration based on the first endpoint and the collection of methods supported.
|
227
|
-
routes_by_regexp.
|
228
|
-
last_route
|
229
|
-
|
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
|
211
|
+
routes_by_regexp.each_value do |routes|
|
212
|
+
last_route = routes.last # Most of the configuration is taken from the last endpoint
|
213
|
+
next if routes.any? { |route| route.request_method == '*' }
|
240
214
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
215
|
+
allowed_methods = routes.map(&:request_method)
|
216
|
+
allowed_methods |= [Rack::HEAD] if !self.class.namespace_inheritable(:do_not_route_head) && allowed_methods.include?(Rack::GET)
|
217
|
+
|
218
|
+
allow_header = self.class.namespace_inheritable(:do_not_route_options) ? allowed_methods : [Rack::OPTIONS] | allowed_methods
|
219
|
+
last_route.app.options[:options_route_enabled] = true unless self.class.namespace_inheritable(:do_not_route_options) || allowed_methods.include?(Rack::OPTIONS)
|
220
|
+
|
221
|
+
@router.associate_routes(last_route.pattern, {
|
222
|
+
endpoint: last_route.app,
|
223
|
+
allow_header: allow_header
|
224
|
+
})
|
225
|
+
end
|
252
226
|
end
|
253
227
|
|
254
228
|
# Allows definition of endpoints that ignore the versioning configuration
|
255
229
|
# used by the rest of your API.
|
256
|
-
def
|
230
|
+
def without_root_prefix_and_versioning
|
257
231
|
old_version = self.class.namespace_inheritable(:version)
|
258
232
|
old_version_options = self.class.namespace_inheritable(:version_options)
|
233
|
+
old_root_prefix = self.class.namespace_inheritable(:root_prefix)
|
259
234
|
|
260
235
|
self.class.namespace_inheritable_to_nil(:version)
|
261
236
|
self.class.namespace_inheritable_to_nil(:version_options)
|
237
|
+
self.class.namespace_inheritable_to_nil(:root_prefix)
|
262
238
|
|
263
239
|
yield
|
264
240
|
|
265
241
|
self.class.namespace_inheritable(:version, old_version)
|
266
242
|
self.class.namespace_inheritable(:version_options, old_version_options)
|
267
|
-
|
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)
|
243
|
+
self.class.namespace_inheritable(:root_prefix, old_root_prefix)
|
279
244
|
end
|
280
245
|
end
|
281
246
|
end
|