We are trying to implement user-determined (on a settings screen) optional gzip compression in our client which uses HttpClient
, so we can log and compare performance across a number of different calls over a period of time. Our first attempt was to simply conditionally add the header as follows:
HttpRequestMessage request = new HttpRequestMessage(Method, Uri);
if (AcceptGzipEncoding)
{
_client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip"));
}
//Send to the server
result = await _client.SendAsync(request);
//Read the content of the result response from the server
content = await result.Content.ReadAsStringAsync();
This created the correct request, but the gzipped response was not decompressed on return, resulting in a garbled response. I found that we had to include the HttpClientHandler
when constructing the HttpClient
:
HttpClient _client = new HttpClient(new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
});
This all works well, but we'd like to change whether the client sends the Accept-Encoding: gzip
header at runtime, and there doesn't appear to be any way to access or change the HttpClientHandler
after it's passed to the HttpClient
constructor. In addition, altering the headers of the HttpRequestMessage
object doesn't have any effect on the headers of the request if they are defined by the HttpClientHandler
.
Is there any way to do this without recreating the HttpClient
each time this changes?
Edit: I've also tried to modify a reference to the HttpClientHandler
to change AutomaticDecompression
at runtime, but that's throwing this exception:
This instance has already started one or more requests. Properties can only be modified before sending the first request.
To compress the HTTP request body, you must attach the HTTP header indicating the sending of HTTP request body compressed in gzip format while sending the request message from the Web Service client. Implement the processing for attaching the HTTP header in the client application.
gzip: It is a compression format using the Lempel-Ziv coding (LZ77), with a 32-bit CRC. compress: It is a compression format using the Lempel-Ziv-Welch (LZW) algorithm. deflate: It is a compression format using the zlib structure, with the deflate compression algorithm.
It means the client can accept a response which has been compressed using the DEFLATE algorithm.
The Accept-Encoding header is used for negotiating content encoding. Accept-Encoding: gzip, deflate. The server responds with the scheme used, indicated by the Content-Encoding response header. Content-Encoding: gzip. Note that the server is not obligated to use any compression method.
You're almost there with the first example, you just need to deflate the stream yourself. MS's GZipSteam will help with this:
HttpRequestMessage request = new HttpRequestMessage(Method, Uri);
if (AcceptGzipEncoding)
{
_client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip"));
}
//Send to the server
result = await _client.SendAsync(request);
//Read the content of the result response from the server
using (Stream stream = await result.Content.ReadAsStreamAsync())
using (Stream decompressed = new GZipStream(stream, CompressionMode.Decompress))
using (StreamReader reader = new StreamReader(decompressed))
{
content = reader.ReadToEnd();
}
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