Request content decompression in ASP.Net Core
Asked Answered
S

3

34

I sometimes need to post larger JSON request payloads to my ASP.Net Core Controllers. The size of the payload warrants (at least in my opinion) compressing it. Because ASP.Net Core Controllers do not appear to support compressed request content out of the box, I've rolled my own middleware.

Implementing this was so trivial that I'm not sure if I'm missing something here. Either because there's a built-in way to achieve this or because I made some major mistake from a security- or performance standpoint?

public class GzipRequestContentEncodingMiddleware
{
    public GzipRequestContentEncodingMiddleware(RequestDelegate next)
    {
        if (next == null)
            throw new ArgumentNullException(nameof(next));

        this.next = next;
    }

    private readonly RequestDelegate next;
    private const string ContentEncodingHeader = "Content-Encoding";
    private const string ContentEncodingGzip = "gzip";
    private const string ContentEncodingDeflate = "deflate";

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.Keys.Contains(ContentEncodingHeader) &&
            (context.Request.Headers[ContentEncodingHeader] == ContentEncodingGzip || 
            context.Request.Headers[ContentEncodingHeader] == ContentEncodingDeflate))
        {
            var contentEncoding = context.Request.Headers[ContentEncodingHeader];
            context.Request.Headers.Remove(ContentEncodingHeader);

            var destination = new MemoryStream();

            using (var decompressor = contentEncoding == ContentEncodingGzip
                ? (Stream) new GZipStream(context.Request.Body, CompressionMode.Decompress, true)
                : (Stream) new DeflateStream(context.Request.Body, CompressionMode.Decompress, true))
            {
                await decompressor.CopyToAsync(destination);
            }

            destination.Seek(0, SeekOrigin.Begin);
            context.Request.Body = destination;
            context.Request.Headers["Content-Length"] = destination.Length.ToString(CultureInfo.InvariantCulture);
        }

        await next(context);
    }
}
Silurid answered 14/3, 2017 at 16:58 Comment(5)
Seems about right for me. But do you really need the memory stream? IMHO it should also work if you assign the compressed stream to the request body. The request isn't rewindable anyways. But code reviews are off topic on SOCensurable
@Censurable It works when I short-circuit things the way you've suggested. But that also means I have to ommit the Content-Length header whose value I'm unable to predict this way and I'm not sure if that is a HTTP protocol violation.Silurid
If you're looking for opinions on your code, you should take your question to Code Review (codereview.stackexchange.com). This is off-topic for Stack Overflow.Swigart
Why re-invent the wheel, give this a try... github.com/msmolka/ZNetCS.AspNetCore.CompressionRegardant
Possible duplicate of What is the best way to compress a request to asp.net core 2 site using HttpClient?Bobbiebobbin
L
8

I know that this is a pretty old post, but just in case if it helps someone, here's a nuget package to perform Request Decompression in .net core

https://github.com/alexanderkozlenko/aspnetcore-request-decompression

Lutero answered 6/2, 2019 at 23:51 Comment(1)
Just asking if this also handles decompression of zlib?Inly
P
3

A new middleware has been introduced in .NET 7 Preview 6 that uses the Content-Encoding HTTP header to automatically identify and decompress requests with compressed content so that the developer of the server does not need to handle this themselves. The request decompression middleware is added using the UseRequestDecompression extension method on IApplicationBuilder and the AddRequestDecompression extension method for IServiceCollection.

Parallelize answered 14/7, 2022 at 11:3 Comment(0)
P
-6

Response Compression middleware and services are provided OOB in ASPNETCORE.

You can use the Microsoft.AspNetCore.ResponseCompression nuget package by following instructions on the ASPNETCORE official docs.

Patsy answered 12/9, 2018 at 21:39 Comment(1)
OP was asking about decompressing requests, not compressing responses. The provided middleware only does the latter, not the former.Batey

© 2022 - 2024 — McMap. All rights reserved.