Skip to content

Instantly share code, notes, and snippets.

@psantiago
Created September 30, 2016 17:49
Show Gist options
  • Save psantiago/a9cd98cefc301703af079bb29e45d7ca to your computer and use it in GitHub Desktop.
Save psantiago/a9cd98cefc301703af079bb29e45d7ca to your computer and use it in GitHub Desktop.
gzip action filter (mostly for web api)
/// <summary>
/// Enables caching by setting cache-control to private (instead of no-cache).
/// By default also enables etags, and sets cache-control max-age to 60 seconds.
/// </summary>
public class GzipActionFilter : ActionFilterAttribute
{
public override async Task OnActionExecutedAsync(HttpActionExecutedContext context, CancellationToken cancellationToken)
{
if (context.Request.Headers.AcceptEncoding.All(i => i.Value != "gzip")) return;
if (context.Response.Content == null) return;
using (var compressedStream = new MemoryStream())
{
//the gzip stream compresses whatever's written to it, NOT the stream passed to it.
//that stream is where it writes the output.
//That seems super confusing to me :/
using (var gZipStream = new GZipStream(compressedStream, CompressionMode.Compress))
{
//copies the existing content to the gzip stream
var existingContent = await context.Response.Content.ReadAsStreamAsync();
existingContent.CopyTo(gZipStream);
}
//due to nonsense around trying to access closed streams, we just copy to an array rather than
//use the stream directly.
context.Response.Content = new ByteArrayContent(compressedStream.ToArray());
}
context.Response.Content.Headers.ContentEncoding.Add("gzip");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment