Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to compress a request to asp.net core 2 site using HttpClient?

I am sending request that can be significantly big(~1Mb) and I am seeing a large delay betweeen when I make the request and when asp.net core logs that it is handling the request. I think I can cut down this time by compressing the request to asp using gzip.

Below is the fairly straight forward way that I am making requests without compression. What is the proper way to implement Gzip request compression on the client requesting side, and once I implement it on the client, what do I need to do for the server side?

using (HttpResponseMessage response = client.PostAsync("Controller/Action", httpContent).Result)
{
    if (response.StatusCode != System.Net.HttpStatusCode.OK)
    {

        throw new Exception(string.Format("Invalid responsecode for http request response {0}: {1}", response.StatusCode, response.ReasonPhrase));
    }
}
like image 610
BillHaggerty Avatar asked Oct 09 '17 20:10

BillHaggerty


People also ask

Is Brotli better than gzip?

Brotli has a better compression ratio (i.e. it produces smaller compressed files) across every level of compression. While GZIP does beat Brotli on speed most of the time, the level you compress at factors into the results you'll see.

Does ASP.NET Core support response compression?

When you're unable to use the compression features of web servers (IIS, Apache, Nginx), ASP.NET Core provides an alternate option, Response Compression middleware.

How many requests per second can ASP.NET Core handle?

7+ Million HTTP requests per second from a single server.


2 Answers

So I got it to work with simple middleware on the server side and not too much work on the client side. I used CompressedContent.cs from WebAPIContrib, as Rex suggested in the comments of his answer, and made the request as shown below. The whole throw-exception-if-not-OK is because I am using Polly wrapped around my request with a Retry and wait policy.

Client Side:

using (var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json"))
using (var compressedContent = new CompressedContent(httpContent, "gzip"))
using (HttpResponseMessage response = client.PostAsync("Controller/Action", compressedContent).Result)
{
    if (response.StatusCode != System.Net.HttpStatusCode.OK)
    {
        throw new Exception(string.Format("Invalid responsecode for http request response {0}: {1}", response.StatusCode, response.ReasonPhrase));
    }
}

Then on the server side I created a simple piece of middleware that wraps the request body stream with the Gzip stream. To use it, you need to add the line app.UseMiddleware<GzipRequestMiddleware>(); before the call to app.UseMvc(); in your Startup.cs's Configure method.

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

    public GzipRequestMiddleware(RequestDelegate next)
    {
        this.next = next ?? throw new ArgumentNullException(nameof(next));
    }

    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];
            var decompressor = contentEncoding == ContentEncodingGzip ? (Stream)new GZipStream(context.Request.Body, CompressionMode.Decompress, true) : (Stream)new DeflateStream(context.Request.Body, CompressionMode.Decompress, true);
            context.Request.Body = decompressor;
        }
        await next(context);
    }
}
like image 190
BillHaggerty Avatar answered Sep 20 '22 09:09

BillHaggerty


You may need to enable compression as shown below

var handler = new HttpClientHandler();  
if (handler.SupportsAutomaticDecompression)  
{
    handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}

var client = new HttpClient(handler);  

MSDN Reference: Using automatic decompression with HttpClient

like image 36
Rex Avatar answered Sep 22 '22 09:09

Rex