grape 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -1
- data/README.md +30 -7
- data/UPGRADING.md +106 -45
- data/lib/grape.rb +2 -2
- data/lib/grape/api/instance.rb +22 -26
- data/lib/grape/dsl/inside_route.rb +33 -11
- data/lib/grape/dsl/validations.rb +18 -1
- data/lib/grape/eager_load.rb +1 -1
- data/lib/grape/endpoint.rb +8 -6
- data/lib/grape/middleware/base.rb +2 -2
- data/lib/grape/middleware/formatter.rb +3 -3
- data/lib/grape/router.rb +24 -29
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
- data/lib/grape/validations/params_scope.rb +3 -3
- data/lib/grape/validations/types/primitive_coercer.rb +1 -2
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +65 -0
- data/spec/grape/dsl/inside_route_spec.rb +175 -33
- data/spec/grape/integration/rack_sendfile_spec.rb +12 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +1 -1
- data/spec/grape/middleware/formatter_spec.rb +1 -1
- data/spec/grape/validations/types/primitive_coercer_spec.rb +60 -4
- data/spec/grape/validations/validators/coerce_spec.rb +86 -0
- data/spec/grape/validations_spec.rb +17 -13
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- metadata +108 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 342f290903dcc993f0e60d0d15bee151f3425abf2b68a191da459d9ac47ac943
|
4
|
+
data.tar.gz: 5b03c2c50e3b485787fd9d7ae64130b7cfe56ca9a9128d51133e46e58562d151
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6f78f911d63d73b8cd2422b8918d53fadfd963e4b212e555f9c8fac8d1dfe801ca2e29a9e1ca236e41a82c1b75a0e503062d5a87430c1821817fae83cfd8ffd
|
7
|
+
data.tar.gz: c856baf9f14a2eebb371f69bd35f6b7a555113e92eb9e35384901df09ac86dfcea691753ef9990123e54a335a0b9dca66b97170fb27a377cf0bb3f4f6e5233ae
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
### 1.4.0 (2020/07/10)
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
* [#1520](https://github.com/ruby-grape/grape/pull/1520): Un-deprecate stream-like objects - [@urkle](https://github.com/urkle).
|
6
|
+
* [#2060](https://github.com/ruby-grape/grape/pull/2060): Drop support for Ruby 2.4 - [@dblock](https://github.com/dblock).
|
7
|
+
* [#2060](https://github.com/ruby-grape/grape/pull/2060): Upgraded Rubocop to 0.84.0 - [@dblock](https://github.com/dblock).
|
8
|
+
* [#2077](https://github.com/ruby-grape/grape/pull/2077): Simplify logic for defining declared params - [@dnesteryuk](https://github.com/dnesteryuk).
|
9
|
+
* [#2084](https://github.com/ruby-grape/grape/pull/2084): Fix memory leak in path normalization - [@fcheung](https://github.com/fcheung).
|
10
|
+
|
11
|
+
#### Fixes
|
12
|
+
|
13
|
+
* [#2067](https://github.com/ruby-grape/grape/pull/2067): Coerce empty string to nil for all primitive types except String - [@petekinnecom](https://github.com/petekinnecom).
|
14
|
+
* [#2064](https://github.com/ruby-grape/grape/pull/2064): Fix Ruby 2.7 deprecation warning in `Grape::Middleware::Base#initialize` - [@skarger](https://github.com/skarger).
|
15
|
+
* [#2072](https://github.com/ruby-grape/grape/pull/2072): Fix `Grape.eager_load!` and `compile!` - [@stanhu](https://github.com/stanhu).
|
16
|
+
* [#2076](https://github.com/ruby-grape/grape/pull/2076): Make route information available for hooks when the automatically generated endpoints are invoked - [@anakinj](https://github.com/anakinj).
|
17
|
+
|
1
18
|
### 1.3.3 (2020/05/23)
|
2
19
|
|
3
20
|
#### Features
|
@@ -52,7 +69,8 @@
|
|
52
69
|
* [#1976](https://github.com/ruby-grape/grape/pull/1976): Ensure classes/modules listed for autoload really exist - [@dnesteryuk](https://github.com/dnesteryuk).
|
53
70
|
* [#1971](https://github.com/ruby-grape/grape/pull/1971): Fix BigDecimal coercion - [@FlickStuart](https://github.com/FlickStuart).
|
54
71
|
* [#1968](https://github.com/ruby-grape/grape/pull/1968): Fix args forwarding in Grape::Middleware::Stack#merge_with for ruby 2.7.0 - [@dm1try](https://github.com/dm1try).
|
55
|
-
* [#1988](https://github.com/ruby-grape/grape/pull/1988):
|
72
|
+
* [#1988](https://github.com/ruby-grape/grape/pull/1988): Refactor the full_messages method and stop overriding full_message - [@hosseintoussi](https://github.com/hosseintoussi).
|
73
|
+
* [#1956](https://github.com/ruby-grape/grape/pull/1956): Comply with Rack spec, fix `undefined method [] for nil:NilClass` error when upgrading Rack - [@ioquatix](https://github.com/ioquatix).
|
56
74
|
|
57
75
|
### 1.3.0 (2020/01/11)
|
58
76
|
|
data/README.md
CHANGED
@@ -156,7 +156,8 @@ content negotiation, versioning and much more.
|
|
156
156
|
|
157
157
|
## Stable Release
|
158
158
|
|
159
|
-
You're reading the documentation for the stable release of Grape,
|
159
|
+
You're reading the documentation for the stable release of Grape, 1.4.0.
|
160
|
+
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
160
161
|
|
161
162
|
## Project Resources
|
162
163
|
|
@@ -1057,13 +1058,13 @@ params do
|
|
1057
1058
|
end
|
1058
1059
|
```
|
1059
1060
|
|
1060
|
-
Note that default values will be passed through to any validation options specified.
|
1061
|
-
The following example will always fail if `:color` is not explicitly provided.
|
1062
|
-
|
1063
1061
|
Default values are eagerly evaluated. Above `:non_random_number` will evaluate to the same
|
1064
1062
|
number for each call to the endpoint of this `params` block. To have the default evaluate
|
1065
1063
|
lazily with each request use a lambda, like `:random_number` above.
|
1066
1064
|
|
1065
|
+
Note that default values will be passed through to any validation options specified.
|
1066
|
+
The following example will always fail if `:color` is not explicitly provided.
|
1067
|
+
|
1067
1068
|
```ruby
|
1068
1069
|
params do
|
1069
1070
|
optional :color, type: String, default: 'blue', values: ['red', 'green']
|
@@ -3166,17 +3167,19 @@ end
|
|
3166
3167
|
|
3167
3168
|
Use `body false` to return `204 No Content` without any data or content-type.
|
3168
3169
|
|
3169
|
-
You can also set the response to a file with `
|
3170
|
+
You can also set the response to a file with `sendfile`. This works with the
|
3171
|
+
[Rack::Sendfile](https://www.rubydoc.info/gems/rack/Rack/Sendfile) middleware to optimally send
|
3172
|
+
the file through your web server software.
|
3170
3173
|
|
3171
3174
|
```ruby
|
3172
3175
|
class API < Grape::API
|
3173
3176
|
get '/' do
|
3174
|
-
|
3177
|
+
sendfile '/path/to/file'
|
3175
3178
|
end
|
3176
3179
|
end
|
3177
3180
|
```
|
3178
3181
|
|
3179
|
-
|
3182
|
+
To stream a file in chunks use `stream`
|
3180
3183
|
|
3181
3184
|
```ruby
|
3182
3185
|
class API < Grape::API
|
@@ -3186,6 +3189,26 @@ class API < Grape::API
|
|
3186
3189
|
end
|
3187
3190
|
```
|
3188
3191
|
|
3192
|
+
If you want to stream non-file data use the `stream` method and a `Stream` object.
|
3193
|
+
This is an object that responds to `each` and yields for each chunk to send to the client.
|
3194
|
+
Each chunk will be sent as it is yielded instead of waiting for all of the content to be available.
|
3195
|
+
|
3196
|
+
```ruby
|
3197
|
+
class MyStream
|
3198
|
+
def each
|
3199
|
+
yield 'part 1'
|
3200
|
+
yield 'part 2'
|
3201
|
+
yield 'part 3'
|
3202
|
+
end
|
3203
|
+
end
|
3204
|
+
|
3205
|
+
class API < Grape::API
|
3206
|
+
get '/' do
|
3207
|
+
stream MyStream.new
|
3208
|
+
end
|
3209
|
+
end
|
3210
|
+
```
|
3211
|
+
|
3189
3212
|
## Authentication
|
3190
3213
|
|
3191
3214
|
### Basic and Digest Auth
|
data/UPGRADING.md
CHANGED
@@ -3,14 +3,79 @@ Upgrading Grape
|
|
3
3
|
|
4
4
|
### Upgrading to >= 1.4.0
|
5
5
|
|
6
|
+
#### Reworking stream and file and un-deprecating stream like-objects
|
7
|
+
|
8
|
+
Previously in 0.16 stream-like objects were deprecated. This release restores their functionality for use-cases other than file streaming.
|
9
|
+
|
10
|
+
This release deprecated `file` in favor of `sendfile` to better document its purpose.
|
11
|
+
|
12
|
+
To deliver a file via the Sendfile support in your web server and have the Rack::Sendfile middleware enabled. See [`Rack::Sendfile`](https://www.rubydoc.info/gems/rack/Rack/Sendfile).
|
13
|
+
```ruby
|
14
|
+
class API < Grape::API
|
15
|
+
get '/' do
|
16
|
+
sendfile '/path/to/file'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
Use `stream` to stream file content in chunks.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class API < Grape::API
|
25
|
+
get '/' do
|
26
|
+
stream '/path/to/file'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
Or use `stream` to stream other kinds of content. In the following example a streamer class
|
32
|
+
streams paginated data from a database.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
class MyObject
|
36
|
+
attr_accessor :result
|
37
|
+
|
38
|
+
def initialize(query)
|
39
|
+
@result = query
|
40
|
+
end
|
41
|
+
|
42
|
+
def each
|
43
|
+
yield '['
|
44
|
+
# Do paginated DB fetches and return each page formatted
|
45
|
+
first = false
|
46
|
+
result.find_in_batches do |records|
|
47
|
+
yield process_records(records, first)
|
48
|
+
first = false
|
49
|
+
end
|
50
|
+
yield ']'
|
51
|
+
end
|
52
|
+
|
53
|
+
def process_records(records, first)
|
54
|
+
buffer = +''
|
55
|
+
buffer << ',' unless first
|
56
|
+
buffer << records.map(&:to_json).join(',')
|
57
|
+
buffer
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class API < Grape::API
|
62
|
+
get '/' do
|
63
|
+
stream MyObject.new(Sprocket.all)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
### Upgrading to >= 1.3.3
|
69
|
+
|
6
70
|
#### Nil values for structures
|
7
71
|
|
8
72
|
Nil values always been a special case when dealing with types especially with the following structures:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
73
|
+
|
74
|
+
- Array
|
75
|
+
- Hash
|
76
|
+
- Set
|
77
|
+
|
78
|
+
The behavior for these structures has change through out the latest releases. For example:
|
14
79
|
|
15
80
|
```ruby
|
16
81
|
class Api < Grape::API
|
@@ -26,9 +91,10 @@ class Api < Grape::API
|
|
26
91
|
# 1.3.2 = nil
|
27
92
|
end
|
28
93
|
```
|
94
|
+
|
29
95
|
For now on, `nil` values stay `nil` values for all types, including arrays, sets and hashes.
|
30
96
|
|
31
|
-
If you want to have the same behavior as 1.3.1, apply a `default` validator
|
97
|
+
If you want to have the same behavior as 1.3.1, apply a `default` validator:
|
32
98
|
|
33
99
|
```ruby
|
34
100
|
class Api < Grape::API
|
@@ -68,10 +134,7 @@ After adding dry-types, Ruby 2.4 or newer is required.
|
|
68
134
|
|
69
135
|
#### Coercion
|
70
136
|
|
71
|
-
[Virtus](https://github.com/solnic/virtus) has been replaced by
|
72
|
-
[dry-types](https://dry-rb.org/gems/dry-types/1.2/) for parameter
|
73
|
-
coercion. If your project depends on Virtus outside of Grape, explicitly
|
74
|
-
add it to your `Gemfile`.
|
137
|
+
[Virtus](https://github.com/solnic/virtus) has been replaced by [dry-types](https://dry-rb.org/gems/dry-types/1.2/) for parameter coercion. If your project depends on Virtus outside of Grape, explicitly add it to your `Gemfile`.
|
75
138
|
|
76
139
|
Here's an example of how to migrate a custom type from Virtus to dry-types:
|
77
140
|
|
@@ -98,10 +161,7 @@ To use dry-types, we need to:
|
|
98
161
|
1. Rename `coerce` to `self.parse`
|
99
162
|
1. Rename `value_coerced?` to `self.parsed?`
|
100
163
|
|
101
|
-
The custom type must have a class-level `parse` method to the model. A
|
102
|
-
class-level `parsed?` is needed if the parsed type differs from the
|
103
|
-
defined type. In the example below, since `SecureUri` is not the same
|
104
|
-
as `URI::HTTPS`, `self.parsed?` is needed:
|
164
|
+
The custom type must have a class-level `parse` method to the model. A class-level `parsed?` is needed if the parsed type differs from the defined type. In the example below, since `SecureUri` is not the same as `URI::HTTPS`, `self.parsed?` is needed:
|
105
165
|
|
106
166
|
```ruby
|
107
167
|
# New dry-types parser
|
@@ -120,21 +180,31 @@ params do
|
|
120
180
|
end
|
121
181
|
```
|
122
182
|
|
183
|
+
#### Coercing to `FalseClass` or `TrueClass` no longer works
|
184
|
+
|
185
|
+
Previous Grape versions allowed this, though it wasn't documented:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
requires :true_value, type: TrueClass
|
189
|
+
requires :bool_value, types: [FalseClass, TrueClass]
|
190
|
+
```
|
191
|
+
|
192
|
+
This is no longer supported, if you do this, your values will never be valid. Instead you should do this:
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
requires :true_value, type: Boolean # in your endpoint you should validate if this is actually `true`
|
196
|
+
requires :bool_value, type: Boolean
|
197
|
+
```
|
198
|
+
|
123
199
|
#### Ensure that Array types have explicit coercions
|
124
200
|
|
125
|
-
Unlike Virtus, dry-types does not perform any implict coercions. If you
|
126
|
-
have any uses of `Array[String]`, `Array[Integer]`, etc. be sure they
|
127
|
-
use a `coerce_with` block. For example:
|
201
|
+
Unlike Virtus, dry-types does not perform any implict coercions. If you have any uses of `Array[String]`, `Array[Integer]`, etc. be sure they use a `coerce_with` block. For example:
|
128
202
|
|
129
203
|
```ruby
|
130
204
|
requires :values, type: Array[String]
|
131
205
|
```
|
132
206
|
|
133
|
-
It's quite common to pass a comma-separated list, such as `tag1,tag2` as
|
134
|
-
`values`. Previously Virtus would implicitly coerce this to
|
135
|
-
`Array(values)` so that `["tag1,tag2"]` would pass the type checks, but
|
136
|
-
with `dry-types` the values are no longer coerced for you. To fix this,
|
137
|
-
you might do:
|
207
|
+
It's quite common to pass a comma-separated list, such as `tag1,tag2` as `values`. Previously Virtus would implicitly coerce this to `Array(values)` so that `["tag1,tag2"]` would pass the type checks, but with `dry-types` the values are no longer coerced for you. To fix this, you might do:
|
138
208
|
|
139
209
|
```ruby
|
140
210
|
requires :values, type: Array[String], coerce_with: ->(val) { val.split(',').map(&:strip) }
|
@@ -201,12 +271,9 @@ In order to make obtaining the name of a mounted class simpler, we've delegated
|
|
201
271
|
|
202
272
|
##### Patching the class
|
203
273
|
|
204
|
-
In an effort to make APIs re-mountable, The class `Grape::API` no longer refers to an API instance,
|
205
|
-
rather, what used to be `Grape::API` is now `Grape::API::Instance` and `Grape::API` was replaced
|
206
|
-
with a class that can contain several instances of `Grape::API`.
|
274
|
+
In an effort to make APIs re-mountable, The class `Grape::API` no longer refers to an API instance, rather, what used to be `Grape::API` is now `Grape::API::Instance` and `Grape::API` was replaced with a class that can contain several instances of `Grape::API`.
|
207
275
|
|
208
|
-
This changes were done in such a way that no code-changes should be required.
|
209
|
-
However, if experiencing problems, or relying on private methods and internal behaviour too deeply, it is possible to restore the prior behaviour by replacing the references from `Grape::API` to `Grape::API::Instance`.
|
276
|
+
This changes were done in such a way that no code-changes should be required. However, if experiencing problems, or relying on private methods and internal behaviour too deeply, it is possible to restore the prior behaviour by replacing the references from `Grape::API` to `Grape::API::Instance`.
|
210
277
|
|
211
278
|
Note, this is particularly relevant if you are opening the class `Grape::API` for modification.
|
212
279
|
|
@@ -229,15 +296,20 @@ end
|
|
229
296
|
|
230
297
|
After the patch, the mounted API is no longer a Named class inheriting from `Grape::API`, it is an anonymous class
|
231
298
|
which inherit from `Grape::API::Instance`.
|
299
|
+
|
232
300
|
What this means in practice, is:
|
301
|
+
|
233
302
|
- Generally: you can access the named class from the instance calling the getter `base`.
|
234
|
-
- In particular: If you need the `name`, you can use `base`.`name
|
303
|
+
- In particular: If you need the `name`, you can use `base`.`name`.
|
235
304
|
|
236
305
|
**Deprecated**
|
306
|
+
|
237
307
|
```ruby
|
238
308
|
payload[:endpoint].options[:for].name
|
239
309
|
```
|
310
|
+
|
240
311
|
**New**
|
312
|
+
|
241
313
|
```ruby
|
242
314
|
payload[:endpoint].options[:for].base.name
|
243
315
|
```
|
@@ -328,8 +400,7 @@ See [#1610](https://github.com/ruby-grape/grape/pull/1610) for more information.
|
|
328
400
|
|
329
401
|
#### The `except`, `except_message`, and `proc` options of the `values` validator are deprecated.
|
330
402
|
|
331
|
-
The new `except_values` validator should be used in place of the `except` and `except_message` options of
|
332
|
-
the `values` validator.
|
403
|
+
The new `except_values` validator should be used in place of the `except` and `except_message` options of the `values` validator.
|
333
404
|
|
334
405
|
Arity one Procs may now be used directly as the `values` option to explicitly test param values.
|
335
406
|
|
@@ -405,9 +476,7 @@ get '/example' #=> before: 405, after: 404
|
|
405
476
|
|
406
477
|
#### Removed param processing from built-in OPTIONS handler
|
407
478
|
|
408
|
-
When a request is made to the built-in `OPTIONS` handler, only the `before` and `after`
|
409
|
-
callbacks associated with the resource will be run. The `before_validation` and
|
410
|
-
`after_validation` callbacks and parameter validations will be skipped.
|
479
|
+
When a request is made to the built-in `OPTIONS` handler, only the `before` and `after` callbacks associated with the resource will be run. The `before_validation` and `after_validation` callbacks and parameter validations will be skipped.
|
411
480
|
|
412
481
|
See [#1505](https://github.com/ruby-grape/grape/pull/1505) for more information.
|
413
482
|
|
@@ -428,8 +497,7 @@ See [#1510](https://github.com/ruby-grape/grape/pull/1510) for more information.
|
|
428
497
|
|
429
498
|
#### The default status code for DELETE is now 204 instead of 200.
|
430
499
|
|
431
|
-
Breaking change: Sets the default response status code for a delete request to 204.
|
432
|
-
A status of 204 makes the response more distinguishable and therefore easier to handle on the client side, particularly because a DELETE request typically returns an empty body as the resource was deleted or voided.
|
500
|
+
Breaking change: Sets the default response status code for a delete request to 204. A status of 204 makes the response more distinguishable and therefore easier to handle on the client side, particularly because a DELETE request typically returns an empty body as the resource was deleted or voided.
|
433
501
|
|
434
502
|
To achieve the old behavior, one has to set it explicitly:
|
435
503
|
```ruby
|
@@ -607,18 +675,14 @@ See [#1114](https://github.com/ruby-grape/grape/pull/1114) for more information.
|
|
607
675
|
|
608
676
|
#### Bypasses formatters when status code indicates no content
|
609
677
|
|
610
|
-
To be consistent with rack and it's handling of standard responses
|
611
|
-
associated with no content, both default and custom formatters will now
|
678
|
+
To be consistent with rack and it's handling of standard responses associated with no content, both default and custom formatters will now
|
612
679
|
be bypassed when processing responses for status codes defined [by rack](https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L567)
|
613
680
|
|
614
681
|
See [#1190](https://github.com/ruby-grape/grape/pull/1190) for more information.
|
615
682
|
|
616
683
|
#### Redirects respond as plain text with message
|
617
684
|
|
618
|
-
`#redirect` now uses `text/plain` regardless of whether that format has
|
619
|
-
been enabled. This prevents formatters from attempting to serialize the
|
620
|
-
message body and allows for a descriptive message body to be provided - and
|
621
|
-
optionally overridden - that better fulfills the theme of the HTTP spec.
|
685
|
+
`#redirect` now uses `text/plain` regardless of whether that format has been enabled. This prevents formatters from attempting to serialize the message body and allows for a descriptive message body to be provided - and optionally overridden - that better fulfills the theme of the HTTP spec.
|
622
686
|
|
623
687
|
See [#1194](https://github.com/ruby-grape/grape/pull/1194) for more information.
|
624
688
|
|
@@ -652,10 +716,7 @@ end
|
|
652
716
|
|
653
717
|
See [#1029](https://github.com/ruby-grape/grape/pull/1029) for more information.
|
654
718
|
|
655
|
-
There is a known issue because of this change. When Grape is used with an older
|
656
|
-
than 1.2.4 version of [warden](https://github.com/hassox/warden) there may be raised
|
657
|
-
the following exception having the [rack-mount](https://github.com/jm/rack-mount) gem's
|
658
|
-
lines as last ones in the backtrace:
|
719
|
+
There is a known issue because of this change. When Grape is used with an older than 1.2.4 version of [warden](https://github.com/hassox/warden) there may be raised the following exception having the [rack-mount](https://github.com/jm/rack-mount) gem's lines as last ones in the backtrace:
|
659
720
|
|
660
721
|
```
|
661
722
|
NoMethodError: undefined method `[]' for nil:NilClass
|
data/lib/grape.rb
CHANGED
@@ -206,12 +206,12 @@ module Grape
|
|
206
206
|
end
|
207
207
|
end
|
208
208
|
|
209
|
-
module
|
209
|
+
module ServeStream
|
210
210
|
extend ::ActiveSupport::Autoload
|
211
211
|
eager_autoload do
|
212
|
-
autoload :FileResponse
|
213
212
|
autoload :FileBody
|
214
213
|
autoload :SendfileResponse
|
214
|
+
autoload :StreamResponse
|
215
215
|
end
|
216
216
|
end
|
217
217
|
end
|
data/lib/grape/api/instance.rb
CHANGED
@@ -192,37 +192,15 @@ module Grape
|
|
192
192
|
# will return an HTTP 405 response for any HTTP method that the resource
|
193
193
|
# cannot handle.
|
194
194
|
def add_head_not_allowed_methods_and_options_methods
|
195
|
-
|
196
|
-
|
197
|
-
self.class.endpoints.each do |endpoint|
|
198
|
-
routes = endpoint.routes
|
199
|
-
routes.each do |route|
|
200
|
-
# using the :any shorthand produces [nil] for route methods, substitute all manually
|
201
|
-
route_key = route.pattern.to_regexp
|
202
|
-
routes_map[route_key] ||= {}
|
203
|
-
route_settings = routes_map[route_key]
|
204
|
-
route_settings[:pattern] = route.pattern
|
205
|
-
route_settings[:requirements] = route.requirements
|
206
|
-
route_settings[:path] = route.origin
|
207
|
-
route_settings[:methods] ||= []
|
208
|
-
if route.request_method == '*' || route_settings[:methods].include?('*')
|
209
|
-
route_settings[:methods] = Grape::Http::Headers::SUPPORTED_METHODS
|
210
|
-
else
|
211
|
-
route_settings[:methods] << route.request_method
|
212
|
-
end
|
213
|
-
route_settings[:endpoint] = route.app
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
195
|
+
versioned_route_configs = collect_route_config_per_pattern
|
217
196
|
# The paths we collected are prepared (cf. Path#prepare), so they
|
218
197
|
# contain already versioning information when using path versioning.
|
219
198
|
# Disable versioning so adding a route won't prepend versioning
|
220
199
|
# informations again.
|
221
200
|
without_root_prefix do
|
222
201
|
without_versioning do
|
223
|
-
|
224
|
-
|
225
|
-
allowed_methods = methods.dup
|
202
|
+
versioned_route_configs.each do |config|
|
203
|
+
allowed_methods = config[:methods].dup
|
226
204
|
|
227
205
|
unless self.class.namespace_inheritable(:do_not_route_head)
|
228
206
|
allowed_methods |= [Grape::Http::Headers::HEAD] if allowed_methods.include?(Grape::Http::Headers::GET)
|
@@ -241,6 +219,25 @@ module Grape
|
|
241
219
|
end
|
242
220
|
end
|
243
221
|
|
222
|
+
def collect_route_config_per_pattern
|
223
|
+
all_routes = self.class.endpoints.map(&:routes).flatten
|
224
|
+
routes_by_regexp = all_routes.group_by { |route| route.pattern.to_regexp }
|
225
|
+
|
226
|
+
# 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: {},
|
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
|
240
|
+
|
244
241
|
# Generate a route that returns an HTTP 405 response for a user defined
|
245
242
|
# path on methods not specified
|
246
243
|
def generate_not_allowed_method(pattern, allowed_methods: [], **attributes)
|
@@ -252,7 +249,6 @@ module Grape
|
|
252
249
|
end
|
253
250
|
not_allowed_methods = supported_methods - allowed_methods
|
254
251
|
return if not_allowed_methods.empty?
|
255
|
-
|
256
252
|
@router.associate_routes(pattern, not_allowed_methods: not_allowed_methods, **attributes)
|
257
253
|
end
|
258
254
|
|