Skip to content

Commit fbf05cc

Browse files
ericproulxclaude
andcommitted
Wrap Rack parameter parsing errors in Grape::Exceptions::RequestError
Replace five specific exception classes (EmptyMessageBody, TooManyMultipartFiles, TooDeepParameters, ConflictingTypes, InvalidParameters) with a single Grape::Exceptions::RequestError that forwards the Rack exception message directly. On Rack 3, a single `rescue Rack::BadRequest` covers all bad-request errors via the marker module. On Rack 2, each exception class is listed explicitly in Grape::RACK_ERRORS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ec1b0fe commit fbf05cc

14 files changed

Lines changed: 97 additions & 129 deletions

UPGRADING.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@ Upgrading Grape
33

44
### Upgrading to >= 3.2
55

6+
#### Rack parameter parsing errors now raise `Grape::Exceptions::RequestError`
7+
8+
Rack errors raised during parameter parsing (malformed multipart, parameter type conflicts, encoding issues, etc.) are now wrapped in `Grape::Exceptions::RequestError` instead of their previous specific exception classes (`Grape::Exceptions::EmptyMessageBody`, `Grape::Exceptions::TooManyMultipartFiles`, `Grape::Exceptions::TooDeepParameters`, `Grape::Exceptions::ConflictingTypes`, `Grape::Exceptions::InvalidParameters`). Those classes have been removed.
9+
10+
If you rescue any of these specific exceptions, update your rescue clauses to use `Grape::Exceptions::RequestError`:
11+
12+
```ruby
13+
# Before
14+
rescue Grape::Exceptions::ConflictingTypes, Grape::Exceptions::TooDeepParameters => e
15+
# ...
16+
17+
# After
18+
rescue Grape::Exceptions::RequestError => e
19+
# ...
20+
```
21+
22+
The error message is now forwarded directly from Rack rather than translated through Grape's locale system. On Rack 3, all Rack bad-request errors share the `Rack::BadRequest` marker module and are covered by a single rescue.
23+
624
#### `endpoint_run_validators.grape` notification no longer fired when there are no validators
725

826
`ActiveSupport::Notifications` subscribers listening to `endpoint_run_validators.grape` will no longer receive an event for endpoints that have no validators. If you rely on this notification to measure every request, subscribe to `endpoint_run.grape` instead, which always fires.

lib/grape.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ module Grape
6363
Rack::OPTIONS
6464
].freeze
6565

66+
# Rack errors that should be rescued and wrapped as Grape::Exceptions::RequestError.
67+
# Rack 3 introduced Rack::BadRequest as a marker module included by all bad request
68+
# exception classes, allowing a single rescue entry to cover them all.
69+
# On Rack 2, these errors are raised as individual exception classes.
70+
RACK_ERRORS =
71+
if defined?(Rack::BadRequest)
72+
[EOFError, Rack::BadRequest]
73+
else
74+
[
75+
EOFError,
76+
Rack::Multipart::MultipartPartLimitError,
77+
Rack::Multipart::MultipartTotalPartLimitError,
78+
Rack::Utils::ParameterTypeError,
79+
Rack::Utils::InvalidParameterError,
80+
Rack::QueryParser::ParamsTooDeepError
81+
]
82+
end.freeze
83+
6684
def self.deprecator
6785
@deprecator ||= ActiveSupport::Deprecation.new('2.0', 'Grape')
6886
end

lib/grape/exceptions/conflicting_types.rb

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/grape/exceptions/empty_message_body.rb

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/grape/exceptions/invalid_parameters.rb

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
module Grape
4+
module Exceptions
5+
class RequestError < Base
6+
def initialize(exception, status: 400)
7+
super(message: exception.message, status: status)
8+
end
9+
end
10+
end
11+
end

lib/grape/exceptions/too_deep_parameters.rb

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/grape/exceptions/too_many_multipart_files.rb

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/grape/locale/en.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ en:
88
at_least_one: 'are missing, at least one parameter must be provided'
99
blank: 'is empty'
1010
coerce: 'is invalid'
11-
conflicting_types: 'query params contains conflicting types'
12-
empty_message_body: 'empty message body supplied with %{body_format} content-type'
1311
exactly_one: 'are missing, exactly one parameter must be provided'
1412
except_values: 'has a value not allowed'
1513
incompatible_option_values: '%{option1}: %{value1} is incompatible with %{option2}: %{value2}'
@@ -20,7 +18,6 @@ en:
2018
invalid_message_body:
2119
problem: 'message body does not match declared format'
2220
resolution: 'when specifying %{body_format} as content-type, you must pass valid %{body_format} in the request''s ''body'' '
23-
invalid_parameters: 'query params contains invalid format or byte sequence'
2421
invalid_response: 'Invalid response'
2522
invalid_version_header:
2623
problem: 'invalid version header'
@@ -48,8 +45,6 @@ en:
4845
presence: 'is missing'
4946
regexp: 'is invalid'
5047
same_as: 'is not the same as %{parameter}'
51-
too_deep_parameters: 'query params are recursively nested over the specified limit (%{limit})'
52-
too_many_multipart_files: 'the number of uploaded files exceeded the system''s configured limit (%{limit})'
5348
unknown_auth_strategy: 'unknown auth strategy: %{strategy}'
5449
unknown_options: 'unknown options: %{options}'
5550
unknown_parameter: 'unknown parameter: %{param}'

lib/grape/middleware/base.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,8 @@ def content_type
7979

8080
def query_params
8181
rack_request.GET
82-
rescue Rack::QueryParser::ParamsTooDeepError
83-
raise Grape::Exceptions::TooDeepParameters.new(Rack::Utils.param_depth_limit)
84-
rescue Rack::Utils::ParameterTypeError
85-
raise Grape::Exceptions::ConflictingTypes
82+
rescue *Grape::RACK_ERRORS => e
83+
raise Grape::Exceptions::RequestError.new(e)
8684
end
8785

8886
private

0 commit comments

Comments
 (0)