Skip to content

Instantly share code, notes, and snippets.

@jonathanpeppers
Last active June 8, 2022 05:39
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathanpeppers/bb0e9c541d28265bdf97f0c50e9acd8b to your computer and use it in GitHub Desktop.
Save jonathanpeppers/bb0e9c541d28265bdf97f0c50e9acd8b to your computer and use it in GitHub Desktop.
DelegatingHandler for GZip in ASP.NET Web API
public class GzipHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content != null &&
request.Content.Headers.ContentType != null &&
(request.Content.Headers.ContentType.MediaType == "application/gzip" ||
request.Content.Headers.ContentType.MediaType == "application/deflate"))
{
string encodingType = request.Content.Headers.ContentType.MediaType.Split('/').Last();
Stream stream;
if (encodingType == "gzip")
{
stream = new GZipStream(await request.Content.ReadAsStreamAsync(), CompressionMode.Decompress);
}
else if (encodingType == "deflate")
{
stream = new DeflateStream(await request.Content.ReadAsStreamAsync(), CompressionMode.Decompress);
}
else
{
throw new HttpException(HttpStatusCode.UnsupportedMediaType, string.Format("Encoding '{0}' is not supported. Only supports gzip or deflate encoding.", encodingType));
}
request.Content = new DecompressedContent(request.Content, stream);
}
var response = await base.SendAsync(request, cancellationToken);
if (response.Content != null &&
response.RequestMessage.Headers.AcceptEncoding != null &&
response.RequestMessage.Headers.AcceptEncoding.Count > 0)
{
string encodingType = response.RequestMessage.Headers.AcceptEncoding.First().Value;
response.Content = new CompressedContent(response.Content, encodingType);
}
return response;
}
}
public class CompressedContent : HttpContent
{
private HttpContent _content;
private string _encodingType;
public CompressedContent(HttpContent content, string encodingType)
{
_content = content;
_encodingType = encodingType.ToLowerInvariant();
if (_encodingType != "gzip" && _encodingType != "deflate")
{
throw new HttpException(HttpStatusCode.UnsupportedMediaType, string.Format("Encoding '{0}' is not supported. Only supports gzip or deflate encoding.", _encodingType));
}
// copy the headers from the original content
foreach (KeyValuePair<string, IEnumerable<string>> header in _content.Headers)
{
Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Headers.ContentEncoding.Add(encodingType);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
if (_encodingType == "gzip")
{
compressedStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: true);
}
else if (_encodingType == "deflate")
{
compressedStream = new DeflateStream(stream, CompressionMode.Compress, leaveOpen: true);
}
try
{
await _content.CopyToAsync(compressedStream);
}
finally
{
compressedStream.Dispose();
}
}
}
public class DecompressedContent : StreamContent
{
public DecompressedContent(HttpContent content, Stream stream) : base(stream)
{
// copy the headers from the original content
foreach (KeyValuePair<string, IEnumerable<string>> header in content.Headers)
{
Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Headers.Remove("Content-Type");
Headers.Add("Content-Type", "application/json");
}
}
@hassanbuttar
Copy link

Hi, May b its too late but after using this handler I am having another issue, When I send the request using postman I never get the response back and postman keeps on trying however the status code 200 is populated on postman but its still loading the contents.
image

@jonathanpeppers
Copy link
Author

@hassanbuttar I wrote this 5+ years ago, I'm not sure if it even works with the latest ASP.NET.

@hassanbuttar
Copy link

@jonathanpeppers I understand this, I am trying to find out the solution but was not able to understand this problem that's why i posted here. I am using Framework 4.8. If you need i can make a sample project for you to understand what's going on (if you are free to help). I am already trying different social channels to get the help for this so hopefully I will be able to find the answers. B.T.W Thanks for the reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment