Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle EOFError raised by Rack #2161

Merged
merged 5 commits into from Feb 10, 2021
Merged

Conversation

bschmeck
Copy link
Contributor

@bschmeck bschmeck commented Feb 9, 2021

In v2.2.0, Rack started raising an EOFError when given an empty body with a multipart upload: rack/rack#1572. Previously, Rack swallowed this error and execution continued normally. This PR translates that error to an InvalidMessageBody exception, letting Grape return a 400 class error, instead of a 500 class error.

Note that the error raised by Rack will change to Rack::Multipart::EmptyContentError in v3 - rack/rack#1688

@bschmeck bschmeck force-pushed the handle-eof-from-rack branch 2 times, most recently from 2676741 to a723b9f Compare February 9, 2021 21:53
In v2.2.0, Rack started raising an EOFError when given an empty body with a
multipart upload - rack/rack#1572  Previously, Rack had
swallowed this error.
@@ -15,6 +15,8 @@ def initialize(env, **options)

def params
@params ||= build_params
rescue EOFError
raise Grape::Exceptions::InvalidMessageBody, 'multipart/form-data'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am concerned that this is hardcoding multipart/form-data, input doesn't have to be this way, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know when Rack would raise this error other than when given a multipart/form-data, but I'm not a Rack expert. I've pushed a commit to use the object's content_type method instead.

This error class seemed the most appropriated, but it requires a content type. I'm happy to create a different error class if that would be preferable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with reusing this error, it makes sense to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second thought, should we create a EmptyMessageBody error?

We most likely are here due to a multipart/form-data Content-Type, but there's
no guarantee of that.

it 'returns a 400 if given an invalid multipart body' do
# Rack swallowed this error until v2.2.0
major, minor, _patch = Rack.release.split('.').map(&:to_i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "correct" way to do this is to use Gem::Version.new(Rack.release) >= ..., see https://code.dblock.org/2020/07/16/comparing-version-numbers-in-ruby.html if it's helpful.

Let's also externalize the if as a spec condition so we see it properly skipped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I figured there had to be a better way.

@@ -15,6 +15,8 @@ def initialize(env, **options)

def params
@params ||= build_params
rescue EOFError
raise Grape::Exceptions::InvalidMessageBody, 'multipart/form-data'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second thought, should we create a EmptyMessageBody error?

Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also add a gemfile and run it as part of the matrix explicitly with this version of Rack, ala https://github.com/ruby-grape/grape/blob/master/gemfiles/rack2.gemfile

Also move the conditional to a spec condition, to properly skip the spec on
versions of Rack that don't raise an error.
@bschmeck
Copy link
Contributor Author

I've cleaned up how the test is skipped for older versions of Rack, added a custom EmptyMessageBody error and explicitly added Rack 2.2 to the test matrix.

I think that addresses all of your comments, but let me know if I missed something.

@dblock dblock merged commit 6a21f80 into ruby-grape:master Feb 10, 2021
@dblock
Copy link
Member

dblock commented Feb 10, 2021

Thanks for hanging in here, great job. Merged.

@dblock
Copy link
Member

dblock commented Feb 10, 2021

Related, we had #2130, maybe you care to resolve it one way or another? I do think a note on all Rack-related issues could be useful somewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants