aspnet / BasicMiddleware

[Archived] Basic middleware components for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
169 stars 84 forks source link

Response Compression allows re-compressing of already compressed responses #305

Closed speige closed 6 years ago

speige commented 6 years ago

I serve pre-compressed static files via a custom middleware (discussed here https://github.com/aspnet/Home/issues/1584)

If I add app.UseResponseCompression(); in Startup.cs Configure method the response will be compressed 2x.

This can obviously be avoided by re-ordering the middleware, but it seems like ResponseCompressionProvider should double-check the Response headers to see if the Content-Encoding value indicates that it's already compresed.

speige commented 6 years ago

i coded up a possible solution. let me know if you'd like a pull request.

    public class CustomResponseCompressionProvider : ResponseCompressionProvider
    {
        public CustomResponseCompressionProvider(IServiceProvider services, IOptions<ResponseCompressionOptions> options) : base(services, options)
        {
        }

        public override bool ShouldCompressResponse(HttpContext context)
        {
            if (!string.IsNullOrWhiteSpace(context.Response.Headers["Content-Encoding"]) && !string.Equals(context.Response.Headers["Content-Encoding"], "identity", StringComparison.InvariantCultureIgnoreCase))
            {
                return false;
            }

            return base.ShouldCompressResponse(context);
        }
    }

It can be used in the ConfigureServices method of Startup.cs like this:

            services.Configure<GzipCompressionProviderOptions>(options => options.Level = System.IO.Compression.CompressionLevel.Fastest);
            services.Configure((ResponseCompressionOptions options) =>
            {
                options.Providers.Add<BrotliCompressionProvider>();
                options.Providers.Add<GzipCompressionProvider>();
                options.EnableForHttps = true;
                options.MimeTypes = new[]
                {
                    // Default
                    "text/plain",
                    "text/css",
                    "application/javascript",
                    "text/html",
                    "application/xml",
                    "text/xml",
                    "application/json",
                    "text/json",

                    // Custom
                    "application/atom+xml",
                    "application/xaml+xml",
                    "application/svg+xml",
                    "image/svg+xml",
                    "application/vnd.ms-fontobject",
                    "font/otf"
                };
            });
            services.TryAddSingleton<IResponseCompressionProvider, CustomResponseCompressionProvider>();

The normal UseResponseCompression(); in Startup.cs Configure should still work.

melnikov77 commented 6 years ago

I have same issue i.e response is double compressed (in my case this happens when I use proxy). Is it possible his fix will be added to ResponseCompressionProvider?

Tratcher commented 6 years ago

Adding a StringValues.IsNullOrEmpty check for Content-Encoding would be reasonable. Are you interested in sending a PR to the release/2.2 branch?

melnikov77 commented 6 years ago

Sure, will do it