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

Upgrading Elastic.Apm.AspNetFullFramework from 1.6.1 to 1.7.1 breaks multipart async request body reading #1113

Closed
WillGunn opened this issue Jan 7, 2021 · 2 comments · Fixed by #1115
Labels
agent-dotnet bug Something isn't working

Comments

@WillGunn
Copy link

WillGunn commented Jan 7, 2021

Describe the bug
In our .net framework web app, targeting .net framework 4.8

To Reproduce
Steps to reproduce the behavior:

  1. Create a controller that implements System.Web.Http.ApiController
  2. Add and setup using default settings the Elastic.Apm.AspNetFullFramework v1.7.1 nuget package
  3. Make an async controller endpoint that makes a multipart async read await Request.Content.ReadAsMultipartAsync();

Expected behavior
I expect APM not to interfere with reading multipart async request streams, especially when we don't have Body capturing enabled.

Here is a stripped down stack trace:

Error reading MIME multipart body part.
System.IO.IOException: Error reading MIME multipart body part. [Source: System.Net.Http.Formatting]
    at System.Net.Http.HttpContentMultipartExtensions.d__9`1.MoveNext() --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at <internal Service>.d__0.MoveNext() in <path to internal service source file>:line 14 --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at <internal ApiController>.d__8.MoveNext() in <path to internal ApiController source file>:line 77
Inner Exception:
System.InvalidOperationException: Unable to read the entity body in Bufferless mode. The request stream has already been buffered. [Source: System.Web.Http.WebHost]
    at System.Web.Http.WebHost.HttpControllerHandler.<>c__DisplayClass18_0.b__1()
    at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.get_StreamContent()
    at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.CreateContentReadStreamAsync()
    at System.Net.Http.HttpContent.ReadAsStreamAsync()
    at System.Net.Http.HttpContentMultipartExtensions.d__9`1.MoveNext()

Endpoint example

[Route]
public async Task<IHttpActionResult> Post()
{
    var content = await Request.Content.ReadAsMultipartAsync(); //exception gets thrown here
    return Ok(content.ToString()); 
}
@WillGunn WillGunn added the bug Something isn't working label Jan 7, 2021
@WillGunn
Copy link
Author

WillGunn commented Jan 7, 2021

Added a reproduction scenario to the sample aspnetframework project:
#1114

russcam added a commit to russcam/apm-agent-dotnet that referenced this issue Jan 11, 2021
This commit fixes a bug where accessing the Request.InputStream
causes the entrie request to be buffered in memory. This has
two repercussions:

1. For many large requests, it can potentially cause out of memory
2. It can interfere with a custom IHostBufferPolicySelector used in
    web API to determine whether to buffer the input stream.

With this fix, the input stream is accessed only when
a SOAP content-type is present and has not already been
read bufferless.

Fixes elastic#1113
@russcam
Copy link
Contributor

russcam commented Jan 11, 2021

Thanks for reporting @WillGunn, I've opened #1115 to address

russcam added a commit that referenced this issue Jan 11, 2021
This commit fixes a bug where accessing the Request.InputStream
causes the entrie request to be buffered in memory. This has
two repercussions:

1. For many large requests, it can potentially cause out of memory
2. It can interfere with a custom IHostBufferPolicySelector used in
    web API to determine whether to buffer the input stream.

With this fix, the input stream is accessed only when
a SOAP content-type is present and has not already been
read bufferless.

Fixes #1113
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
agent-dotnet bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants