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));
}
}
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.
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.
7+ Million HTTP requests per second from a single server.
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);
}
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With