-
-
Save stefanolsen/07c48824f7062115313a92e9313e0958 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.IO.Compression; | |
using System.Threading.Tasks; | |
using Brotli; // Install the Brotli.NET NuGet package. | |
namespace WebApiDemo.WebApi | |
{ | |
public class BrotliCompressor : ICompressor | |
{ | |
public string EncodingType => "br"; | |
public async Task Compress(Stream source, Stream destination) | |
{ | |
using (Stream compressionStream = new BrotliStream(destination, CompressionMode.Compress)) | |
{ | |
await source.CopyToAsync(compressionStream); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Net; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
namespace WebApiDemo.WebApi | |
{ | |
public class CompressedContent : HttpContent | |
{ | |
private readonly HttpContent _content; | |
private readonly ICompressor _compressor; | |
public CompressedContent(HttpContent content, ICompressor compressor) | |
{ | |
_content = content; | |
_compressor = compressor ?? throw new ArgumentNullException(nameof(compressor)); | |
foreach (var header in content.Headers) | |
{ | |
Headers.TryAddWithoutValidation(header.Key, header.Value); | |
} | |
} | |
protected override bool TryComputeLength(out long length) | |
{ | |
length = -1; | |
return false; | |
} | |
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) | |
{ | |
if (stream == null) | |
{ | |
throw new ArgumentNullException(nameof(stream)); | |
} | |
if (_content == null) | |
{ | |
return; | |
} | |
using (Stream contentStream = await _content.ReadAsStreamAsync()) | |
{ | |
await _compressor.Compress(contentStream, stream); | |
} | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if (!disposing) | |
{ | |
return; | |
} | |
_content?.Dispose(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Net.Http; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace WebApiDemo.WebApi | |
{ | |
public class CompressionHandler : DelegatingHandler | |
{ | |
private readonly IReadOnlyDictionary<string, ICompressor> _compressors; | |
public CompressionHandler() | |
{ | |
_compressors = new Dictionary<string, ICompressor> | |
{ | |
{"br", new BrotliCompressor()}, | |
{"gzip", new GZipCompressor()}, | |
{"deflate", new DeflateCompressor()}, | |
{"identity", null} | |
}; | |
} | |
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | |
{ | |
var response = await base.SendAsync(request, cancellationToken); | |
if (!ShouldCompressResponse(response.Content)) | |
{ | |
return response; | |
} | |
var encodings = request.Headers.AcceptEncoding; | |
if (encodings == null || | |
encodings.Count == 0) | |
{ | |
return response; | |
} | |
foreach (var encoding in encodings) | |
{ | |
if (!_compressors.TryGetValue(encoding.Value, out var compressor)) | |
{ | |
continue; | |
} | |
if (compressor == null) | |
{ | |
break; | |
} | |
response.Content = new CompressedContent(response.Content, compressor); | |
response.Content.Headers.ContentMD5 = null; | |
response.Content.Headers.ContentLength = null; | |
response.Content.Headers.ContentEncoding.Add(compressor.EncodingType); | |
response.Headers.Vary.ParseAdd("Accept-Encoding"); | |
break; | |
} | |
return response; | |
} | |
private static bool ShouldCompressResponse(HttpContent content) | |
{ | |
if (content.Headers.ContentRange != null || | |
content.Headers.ContentEncoding.Count > 0) | |
{ | |
return false; | |
} | |
switch (content.Headers.ContentType.MediaType) | |
{ | |
case "application/json": | |
case "application/xml": | |
case "text/html": | |
case "text/json": | |
case "text/plain": | |
case "text/xml": | |
return true; | |
default: | |
return false; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.IO.Compression; | |
using System.Threading.Tasks; | |
namespace WebApiDemo.WebApi | |
{ | |
public class DeflateCompressor : ICompressor | |
{ | |
public string EncodingType => "deflate"; | |
public async Task Compress(Stream source, Stream destination) | |
{ | |
using (Stream compressionStream = new DeflateStream(destination, CompressionMode.Compress)) | |
{ | |
await source.CopyToAsync(compressionStream); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.IO.Compression; | |
using System.Threading.Tasks; | |
namespace WebApiDemo.WebApi | |
{ | |
public class GZipCompressor : ICompressor | |
{ | |
public string EncodingType => "gzip"; | |
public async Task Compress(Stream source, Stream destination) | |
{ | |
using (Stream compressionStream = new GZipStream(destination, CompressionMode.Compress)) | |
{ | |
await source.CopyToAsync(compressionStream); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Threading.Tasks; | |
namespace WebApiDemo.WebApi | |
{ | |
public interface ICompressor | |
{ | |
string EncodingType { get; } | |
Task Compress(Stream source, Stream destination); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using EPiServer.Framework; | |
using EPiServer.Framework.Initialization; | |
using System.Web.Http; | |
namespace WebApiDemo.WebApi | |
{ | |
public class InitializeSite : IInitializableModule | |
{ | |
public void Initialize(InitializationEngine context) | |
{ | |
GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new CompressionHandler()); | |
} | |
public void Uninitialize(InitializationEngine context) | |
{ | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment