-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Fix HttpLoggingMiddleware Request/Response bodies logging in case of stream being closed by a subsequent middleware #61490
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
base: main
Are you sure you want to change the base?
Conversation
…stream being closed by a subsequent middleware (dotnet#61489)
Thanks for your PR, @@ExtraClock. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
@dotnet-policy-service agree |
Hi @BrennanConroy ! Is there a chance for this PR to make it into the v10 release? Since it's my first PR, I'm not sure if there is any additional action I have to take to move this thing forward. |
|
||
public override void Close() | ||
{ | ||
if (!HasLogged) |
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.
Can we pass HttpLoggingInterceptorContext
into the ctor like we do for the response stream and then check if body logging is enabled before getting the string?
return result; | ||
} | ||
|
||
public override void Close() |
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.
Stream.Dispose()
calls Close()
which could then re-create the string just to throw it away. Maybe we should set _logBody
to false once one of the LogResponseBody()
methods is called.
I think the request stream impl is fine, but we should double-check and maybe add a comment about the assumption.
// (1) The subsequent middleware reads right up to the buffer size (guided by the ContentLength header) | ||
while (contentLengthBytesLeft > 0) | ||
{ | ||
var res = await c.Request.Body.ReadAsync(arr, 0, (int)Math.Min(arr.Length, contentLengthBytesLeft)); |
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.
nit?
var res = await c.Request.Body.ReadAsync(arr, 0, (int)Math.Min(arr.Length, contentLengthBytesLeft)); | |
var res = await c.Request.Body.ReadAsync(arr, 0, arr.Length); |
|
||
Assert.Contains(TestSink.Writes, w => w.Message.Contains(expected)); | ||
} | ||
|
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.
Could we add a test for options.CombineLogs = true
and both Request and Response?
Fix HttpLoggingMiddleware Request/Response bodies logging in case of stream being closed by a subsequent middleware (#61489)
Preserve buffer contents until it is consumed by the
HttpLoggingMiddleware
Description
Fixes #61489
When the subsequent middleware closes request/response stream, the
BufferingStream
callsReset
which leads to an empty body being logged.The request stream might be closed if the subsequent middleware follows the
ContentLength
header to sense the end of the stream (instead of reading it to the end).The response stream might be closed without any additional preconditions, just because the subsequent middleware decided to do so.
A real-life example of such a middleware is
CoreWCF
BasicHttpBinding
: inputStream.Close, _outputStream.Close