-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 malformed http requests #5041
Handle malformed http requests #5041
Conversation
116894d
to
dae71c6
Compare
src/http/request.cr
Outdated
return new method, resource, headers, body, http_version | ||
begin | ||
HTTP.parse_headers_and_body(io) do |headers, body| | ||
return new method, resource, headers, body, http_version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure that you need to keep this code organization with added rescue block.
Why not something like
begin
HTTP.parse_headers_and_body(io) do |headers, body|
new method, resource, headers, body, http_version
end
rescue ex : ArgumentError
BadRequest.new
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akzhan that doesn't work, there's a case where parse_headers_and_body
returns without yielding which isnt handled.
src/http/request.cr
Outdated
HTTP.parse_headers_and_body(io) do |headers, body| | ||
return new method, resource, headers, body, http_version | ||
end | ||
rescue ex : ArgumentError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure if this is the correct way to detect this. It feels to broad. I'm not sure what would be a better approach though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RX14 To clarify: are you thinking about more exceptions which could be thrown and would be handled like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps non-ArgumentError
exceptions would be thrown, perhaps new
would throw an exception. This PR is a great improvement but perhaps we could implement it a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The best way probably would be not rescuing the exception but handling the case that triggers it explicitly/differently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally no exception should be raised nor rescued. We should maybe have a method to add a header and return false
or nil
if it's not valid, instead of raising.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also some tests would be awesome :)
Pushed next version. I've added |
src/http/common.cr
Outdated
@@ -59,6 +59,7 @@ module HTTP | |||
end | |||
|
|||
name, value = parse_header(line) | |||
break unless headers.valid_value?(value) | |||
headers.add(name, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest headers.add(name, value) if headers.valid_value?(value)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This checks the validity twice. I suggest adding add?
method that returns false
if it's not valid, true
otherwise.
Added |
src/http/headers.cr
Outdated
self | ||
end | ||
|
||
def add?(key, value : String) | ||
add?(key, [value]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allocates an array. The same for add(key, String)
. I prefer it not to allocate (like before, have different implementations of the method)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe we can just allow to pass a tuple here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asterite updated.
Any other suggestions?
Fixes #4878. ArgumentError is thrown while parsing, so it is better to catch it and return BadRequest.