Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core disable Request Buffering (not response buffering)

I've found a good answer for control of response buffering. But I need to disable REQUEST buffering.

Short version of the problem:

I've found that there is a buffer in the background, filling up with request data. Breakpointing the request method doesn't pause this process, so its clearly being done by a background thread. I've followed some instructions (such as turning off FormValueProviderFactory) but they don't prevent this behaviour.

Long version of the problem:

I've implemented the code here.

The sample creates a filter attribute called DisableFormValueModelBindingAttribute which the docs claim prevents the file being loaded into memory, but it doesn't have this effect. The filter is hit AFTER the request starts to be streamed.

But I've found that the entire request is still buffered into memory. It hits the request memory limit and starts to be stored in disk instead, but this is causing the server to run out of disk space. I have only a few hundred MB to work with as the service is hosted in docker. What I really need is for the multipart request to be buffered only up to the point where I can read it.

I'm using .net core 2.1 with AspNetCore 2.1.1

A note on Request.EnableBuffering

The name is incorrect - the request is always buffered, what this actually does is enable request rewind.

A note on IHttpBufferingFeature.DisableBuffering

This is is obselete. It has no implementation details. The obselete tag says

[Obsolete("See IHttpRequestBodyFeature or IHttpResponseBodyFeature DisableBuffering", error: true)]

but IHttpRequestBodyFeature doesn't exist.

Disappointing because I got excited when this answer appeared!

More information

After some experiments, I have figured out a few things. I moved the request out of a controller and into a middleware.

app.Use ((context, next) =>
{

    var Request = context.Request;

    if (MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
    {
        // a breakpoint here doesn't stop the upload
        var path = Request.Path;

// ...

But I find that there is a background thread filling the request buffer. I set a breakpoint inside the middleware, but I can still see the upload occurring in the background. The request buffer is still filling.

The answer may have something to do with possible configurations one can make to HttpRequestFeature.

Further information

in the callback from UseKestrel you can configure limits and there is a limit

called "MaxRequestBufferSize"

But this is 1MB by default. So clearly its not responsible for the full request being buffered to disk.

I also found a github issue regarding buffering being configurable, mostly just a complaint that it is not. This does not fill me with confidence.

like image 423
speciesUnknown Avatar asked Aug 13 '20 13:08

speciesUnknown


1 Answers

At the time of writing, this is not possible.

IHttpRequestBodyFeature is not implemented or exposed, so there isn't a method available for us to call to disable request buffering. There is only a way to disable response buffering in IHttpResponseBodyFeature using the DisableBuffering method.

I searched on GitHub and found minimal results for IHttpRequestBodyFeature https://github.com/search?q=IHttpRequestBodyFeature&type= furthermore supporting the idea the interface is not available or exposed to us yet. If you search IHttpResponseBodyFeature on the other hand you get lots of results from dotnet and aptnetcore.

I recommend an issue be submitted for IHttpRequestBodyFeature not being available here: https://github.com/dotnet/aspnetcore/issues

I cannot find a way to disable request buffering in IHttpResponseFeature. There is no method provided to do so. However with IHttpResponseBodyFeature there is a method to disable response buffering; below is an example:

  1. Add the following namespace

    using Microsoft.AspNetCore.Http.Features;

  2. In the IActionResults where you want Response Buffering disabled use the DisableBuffering() method which:

Opts out of write buffering for the response

var bufferingFeature2 = HttpContext.Features.Get<IHttpResponseBodyFeature>();
bufferingFeature2?.DisableBuffering();
like image 93
vvvv4d Avatar answered Nov 04 '22 17:11

vvvv4d