-
Notifications
You must be signed in to change notification settings - Fork 5k
Enforce HTTP request Content-Length correctness #62541
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
Enforce HTTP request Content-Length correctness #62541
Conversation
Tagging subscribers to this area: @dotnet/ncl Issue DetailsFixes #62258 Like is already the case for HTTP/3, throw on an attempt to write too much request content. This means the server will never receive more than Also throw if we end up sending too few bytes.
|
src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
Show resolved
Hide resolved
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.
LGTM, thanks.
@@ -414,8 +422,7 @@ private async ValueTask WriteRequestContentAsync(ReadOnlyMemory<byte> buffer, Ca | |||
|
|||
if (buffer.Length > _requestContentLengthRemaining) | |||
{ | |||
string msg = SR.net_http_content_write_larger_than_content_length; | |||
throw new IOException(msg, new HttpRequestException(msg)); | |||
throw new HttpRequestException(SR.net_http_content_write_larger_than_content_length); |
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.
Do we care about this being an IOException
?
It's technically a combination of IO + wrong headers.
Currently you would get
new HttpRequestException(
net_http_content_stream_copy_error,
new IOException(
net_http_content_write_larger_than_content_length,
new HttpRequestException(
net_http_content_write_larger_than_content_length)))
after this PR
new HttpRequestException(
net_http_content_write_larger_than_content_length)
(this extends to the rest of the exceptions we are throwing in this PR)
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 assume the change here is to provide the same exception chain as with H/2 and HTTP/1.1? If so, I don't see a reason against.
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 understand not wanting to change the outer exception type at this point, but why wouldn't this cause an InvalidOperationException
? That's what gets thrown by Kestrel if you try to write too much to the response stream after setting a Content-Length
header. To me, it indicates a bug in the program.
Edit: On second thought, why not change the outer exception type? I hope nothing is relying on HttpClient throwing an HttpRequestException if they give it a too-large request body.
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.
why not change the outer exception type? I hope nothing is relying on HttpClient throwing an HttpRequestException
HttpClient
will always try to throw either a TaskCanceledException
or an HttpRequestException
.
Aside from initial argument validation, If something else gets thrown somewhere, we'll wrap it in HttpRequestException
.
Sending too much or too little is the same kind of issue - the header you gave us doesn't match the content. Ideally, the user should see a similar kind of error.
why wouldn't this cause an InvalidOperationException? That's what gets thrown by Kestrel if you try to write too much to the response stream
Most HttpClient
users won't actually do the WriteAsync
that goes over the limit themselves. They will use the built-in HttpContent
types.
var content = new StreamContent(myStream);
content.Headers.ContentLength = someContentLength;
await client.PostAsync("foo", content);
I wouldn't expect this to throw InvalidOperationException
as a user. It's not something I would consider an invalid operation, but more an argument/input exception.
Similarly, I wouldn't expect this to throw something different if my content length calculation was off in the other direction.
Fixes #62258
Like is already the case for HTTP/3, throw on an attempt to write too much request content. This means the server will never receive more than
Content-Length
bytes.Also throw if we end up sending too few bytes.