Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable chunking in ASP.NET Core

Tags:

I'm using an ASP.NET Core Azure Web App to provide a RESTful API to a client, and the client doesn't handle chunking correctly.

Is it possible to completely turn off Transfer-Encoding: chunked, either at the controller level or in file web.config?

I'm returning a JsonResult somewhat like this:

[HttpPost]
[Produces("application/json")]
public IActionResult Post([FromBody] AuthRequest RequestData)
{
    AuthResult AuthResultData = new AuthResult();

    return Json(AuthResultData);
}
like image 288
Iain Brown Avatar asked Jun 22 '16 10:06

Iain Brown


People also ask

What is chunking in ASP NET Core?

ASP.NET Core defaults to chunked if you do not set the content-length. This allows responses to be sent immediately without buffering and helps minimize latency, memory overhead, etc.. Why is chunking a problem for you? Sorry, something went wrong. We have a relay service that forwards requests and responses to and from a server.

What is chunked content length in http?

All HTTP/1.1 responses must set Content-Length or Transfer-Encoding: chunked. ASP.NET Core defaults to chunked if you do not set the content-length. This allows responses to be sent immediately without buffering and helps minimize latency, memory overhead, etc..

How do I chunk the data in a web class?

Specifically, implement the WriteXml and ReadXml methods to chunk the data. On the server machine, the Web method must turn off ASP.NET buffering and return a type that implements IXmlSerializable. The type that implements IXmlSerializable chunks the data in the WriteXml method.

Is there a way to turn off chunking from the server sending?

When copying headers in a proxy/relay you should filter out the Transfer-Encoding: chunked header, most servers will re-add it if needed. Is there a way to easily turn chunking off from the server sending the responses? No. Chunking can only be disabled by setting the Content-Length header, which often requires buffering to calculate.


2 Answers

How to get rid of chunking in .NET Core 2.2:

The trick is to read the response body into your own MemoryStream, so you can get the length. Once you do that, you can set the content-length header, and IIS won't chunk it. I assume this would work for Azure too, but I haven't tested it.

Here's the middleware:

public class DeChunkerMiddleware
{
    private readonly RequestDelegate _next;

    public DeChunkerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var originalBodyStream = context.Response.Body;
        using (var responseBody = new MemoryStream())
        {
            context.Response.Body = responseBody;
            long length = 0;
            context.Response.OnStarting(() =>
            {
                context.Response.Headers.ContentLength = length;
                return Task.CompletedTask;
            });
            await _next(context);

            // If you want to read the body, uncomment these lines.
            //context.Response.Body.Seek(0, SeekOrigin.Begin);
            //var body = await new StreamReader(context.Response.Body).ReadToEndAsync();

            length = context.Response.Body.Length;
            context.Response.Body.Seek(0, SeekOrigin.Begin);
            await responseBody.CopyToAsync(originalBodyStream);
        }
    }
}

Then add this in Startup:

app.UseMiddleware<DeChunkerMiddleware>();

It needs to be before app.UseMvC().

like image 85
Pharylon Avatar answered Sep 21 '22 17:09

Pharylon


In ASP.NET Core, this seems to work across hosts:

response.Headers["Content-Encoding"] = "identity";
response.Headers["Transfer-Encoding"] = "identity";

Indicates the identity function (i.e., no compression, nor modification). This token, except if explicitly specified, is always deemed acceptable.

  • Content-Encoding
  • Transfer-Encoding

This also works when you explicitly disable response buffering:

var bufferingFeature = httpContext.Features.Get<IHttpBufferingFeature>();
bufferingFeature?.DisableResponseBuffering();
like image 42
George Tsiokos Avatar answered Sep 22 '22 17:09

George Tsiokos