ASP.NET 核心禁用请求缓冲(不是响应缓冲)

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

我找到了控制响应缓冲的好答案。但是我需要禁用请求缓冲。

问题的简短版本:

我发现后台有一个缓冲区,正在填充请求数据。断点请求方法不会暂停此过程,因此它显然是由后台线程完成的。我遵循了一些说明(例如关闭 FormValueProviderFactory),但它们并没有阻止这种行为。

长版问题:

我已经实现了代码 here

该示例创建了一个名为 DisableFormValueModelBindingAttribute 的过滤器属性,文档声称该属性可防止将文件加载到内存中,但它没有这种效果。在开始流式传输请求后命中过滤器。

但我发现整个请求仍然缓冲到内存中。它达到了请求内存限制并开始存储在磁盘中,但这导致服务器 运行 磁盘不足 space。由于该服务托管在 docker 中,因此我只有几百 MB 可以使用。我真正需要的是 将多部分请求缓冲到我可以读取的程度

我正在使用 .net core 2.1 和 AspNetCore 2.1.1

关于 Request.EnableBuffering

的注释

名称不正确 - 请求始终被缓冲,这实际上是启用请求倒带。

关于 IHttpBufferingFeature.DisableBuffering

的注释

这已经过时了。它没有实现细节。过时的标签说

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

但是 IHttpRequestBodyFeature doesn't exist.

令人失望,因为当这个答案出现时我很兴奋!

更多信息

经过一些实验,我弄明白了一些事情。我将请求从控制器移到了中间件中。

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;

// ...

但是我发现有一个后台线程在填充请求缓冲区。我在中间件内设置了一个断点,但我仍然可以看到上传发生在后台。请求缓冲区仍在填充。

答案可能与可以对 HttpRequestFeature 进行的可能配置有关。

更多信息

在 UseKestrel 的回调中你可以配置限制并且有一个限制

称为“MaxRequestBufferSize”

但默认情况下这是 1MB。很明显,它不负责将整个请求缓冲到磁盘。

我还发现 a github issue 关于缓冲是可配置的,主要是抱怨它不是。这让我没有信心。

在撰写本文时,这是不可能的。

IHttpRequestBodyFeature 未实现或公开,因此我们无法调用禁用请求缓冲的方法。只有一种方法可以使用 DisableBuffering 方法在 IHttpResponseBodyFeature 中禁用响应缓冲。

我在 GitHub 上搜索,发现 IHttpRequestBodyFeature 的结果很少 https://github.com/search?q=IHttpRequestBodyFeature&type= 进一步支持接口不可用或尚未向我们公开的想法。另一方面,如果你搜索 IHttpResponseBodyFeature,你会得到很多来自 dotnet 和 aptnetcore 的结果。

我建议提交一个问题 IHttpRequestBodyFeature 此处不可用: https://github.com/dotnet/aspnetcore/issues

我无法在 IHttpResponseFeature 中找到禁用请求缓冲的方法。没有 method 提供这样做。但是 IHttpResponseBodyFeature 有一个 method 来禁用响应缓冲;下面是一个例子:

  1. 添加以下命名空间

    using Microsoft.AspNetCore.Http.Features;

  2. IActionResults 中你想禁用 Response Buffering 使用 DisableBuffering() 方法其中:

Opts out of write buffering for the response

var bufferingFeature2 = HttpContext.Features.Get<IHttpResponseBodyFeature>();
bufferingFeature2?.DisableBuffering();