#108 Move compression providers back to options
This commit is contained in:
Родитель
88b78e7233
Коммит
e7b41c4f53
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
@ -18,9 +18,13 @@ namespace ResponseCompressionSample
|
|||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<ICompressionProvider, GzipCompressionProvider>();
|
||||
services.AddSingleton<ICompressionProvider, CustomCompressionProvider>();
|
||||
services.AddResponseCompression("text/plain", "text/html");
|
||||
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
|
||||
services.AddResponseCompression(options =>
|
||||
{
|
||||
options.Providers.Add<GzipCompressionProvider>();
|
||||
options.Providers.Add<CustomCompressionProvider>();
|
||||
options.MimeTypes = new[] { "text/plain", "text/html" };
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
|
@ -63,10 +67,7 @@ namespace ResponseCompressionSample
|
|||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.UseConnectionLogging();
|
||||
})
|
||||
.UseKestrel()
|
||||
// .UseWebListener()
|
||||
.ConfigureLogging(factory =>
|
||||
{
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
#if NETSTANDARD1_3
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.AspNetCore.ResponseCompression
|
||||
{
|
||||
/// <summary>
|
||||
/// A Collection of ICompressionProvider's that also allows them to be instantiated from an <see cref="IServiceProvider" />.
|
||||
/// </summary>
|
||||
public class CompressionProviderCollection : Collection<ICompressionProvider>
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a type representing an <see cref="ICompressionProvider"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Provider instances will be created using an <see cref="IServiceProvider" />.
|
||||
/// </remarks>
|
||||
public void Add<TCompressionProvider>() where TCompressionProvider : ICompressionProvider
|
||||
{
|
||||
Add(typeof(TCompressionProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type representing an <see cref="ICompressionProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="providerType">Type representing an <see cref="ICompressionProvider"/>.</param>
|
||||
/// <remarks>
|
||||
/// Provider instances will be created using an <see cref="IServiceProvider" />.
|
||||
/// </remarks>
|
||||
public void Add(Type providerType)
|
||||
{
|
||||
if (providerType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(providerType));
|
||||
}
|
||||
|
||||
if (!typeof(ICompressionProvider).IsAssignableFrom(providerType))
|
||||
{
|
||||
throw new ArgumentException($"The provider must implement {nameof(ICompressionProvider)}", nameof(providerType));
|
||||
}
|
||||
|
||||
var factory = new CompressionProviderFactory(providerType);
|
||||
Add(factory);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.ResponseCompression
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a placeholder for the CompressionProviderCollection that allows creating the given type via
|
||||
/// an <see cref="IServiceProvider" />.
|
||||
/// </summary>
|
||||
internal class CompressionProviderFactory : ICompressionProvider
|
||||
{
|
||||
internal CompressionProviderFactory(Type providerType)
|
||||
{
|
||||
ProviderType = providerType;
|
||||
}
|
||||
|
||||
internal Type ProviderType { get; }
|
||||
|
||||
internal ICompressionProvider CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (serviceProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serviceProvider));
|
||||
}
|
||||
|
||||
return (ICompressionProvider)ActivatorUtilities.CreateInstance(serviceProvider, ProviderType, Type.EmptyTypes);
|
||||
}
|
||||
|
||||
string ICompressionProvider.EncodingName
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
bool ICompressionProvider.SupportsFlush
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
Stream ICompressionProvider.CreateStream(Stream outputStream)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.ResponseCompression
|
||||
{
|
||||
|
@ -11,6 +13,22 @@ namespace Microsoft.AspNetCore.ResponseCompression
|
|||
/// </summary>
|
||||
public class GzipCompressionProvider : ICompressionProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of GzipCompressionProvider with options.
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
public GzipCompressionProvider(IOptions<GzipCompressionProviderOptions> options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
Options = options.Value;
|
||||
}
|
||||
|
||||
private GzipCompressionProviderOptions Options { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string EncodingName => "gzip";
|
||||
|
||||
|
@ -29,15 +47,10 @@ namespace Microsoft.AspNetCore.ResponseCompression
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// What level of compression to use for the stream.
|
||||
/// </summary>
|
||||
public CompressionLevel Level { get; set; } = CompressionLevel.Fastest;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Stream CreateStream(Stream outputStream)
|
||||
{
|
||||
return new GZipStream(outputStream, Level, leaveOpen: true);
|
||||
return new GZipStream(outputStream, Options.Level, leaveOpen: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO.Compression;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.ResponseCompression
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for the GzipCompressionProvider
|
||||
/// </summary>
|
||||
public class GzipCompressionProviderOptions : IOptions<GzipCompressionProviderOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// What level of compression to use for the stream. The default is Fastest.
|
||||
/// </summary>
|
||||
public CompressionLevel Level { get; set; } = CompressionLevel.Fastest;
|
||||
|
||||
/// <inheritdoc />
|
||||
GzipCompressionProviderOptions IOptions<GzipCompressionProviderOptions>.Value => this;
|
||||
}
|
||||
}
|
|
@ -20,5 +20,10 @@ namespace Microsoft.AspNetCore.ResponseCompression
|
|||
/// Enable compression on HTTPS connections may expose security problems.
|
||||
/// </summary>
|
||||
public bool EnableForHttps { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The ICompressionProviders to use for responses.
|
||||
/// </summary>
|
||||
public CompressionProviderCollection Providers { get; } = new CompressionProviderCollection();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,28 +20,37 @@ namespace Microsoft.AspNetCore.ResponseCompression
|
|||
/// <summary>
|
||||
/// If no compression providers are specified then GZip is used by default.
|
||||
/// </summary>
|
||||
/// <param name="providers">Compression providers to use, if any.</param>
|
||||
/// <param name="services">Services to use when instantiating compression providers.</param>
|
||||
/// <param name="options"></param>
|
||||
public ResponseCompressionProvider(IEnumerable<ICompressionProvider> providers, IOptions<ResponseCompressionOptions> options)
|
||||
public ResponseCompressionProvider(IServiceProvider services, IOptions<ResponseCompressionOptions> options)
|
||||
{
|
||||
if (providers == null)
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(providers));
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
_providers = providers.ToArray();
|
||||
_providers = options.Value.Providers.ToArray();
|
||||
if (_providers.Length == 0)
|
||||
{
|
||||
_providers = new [] { new GzipCompressionProvider() };
|
||||
// Use the factory so it can resolve IOptions<GzipCompressionProviderOptions> from DI.
|
||||
_providers = new ICompressionProvider[] { new CompressionProviderFactory(typeof(GzipCompressionProvider)) };
|
||||
}
|
||||
for (var i = 0; i < _providers.Length; i++)
|
||||
{
|
||||
var factory = _providers[i] as CompressionProviderFactory;
|
||||
if (factory != null)
|
||||
{
|
||||
_providers[i] = factory.CreateInstance(services);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.Value.MimeTypes == null || !options.Value.MimeTypes.Any())
|
||||
{
|
||||
throw new InvalidOperationException("No MIME types specified");
|
||||
throw new InvalidOperationException("No MIME types specified.");
|
||||
}
|
||||
_mimeTypes = new HashSet<string>(options.Value.MimeTypes, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -12,6 +13,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
|
@ -108,6 +110,37 @@ namespace Microsoft.AspNetCore.ResponseCompression.Tests
|
|||
CheckResponseCompressed(response, expectedBodyLength: 24);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GZipCompressionProvider_OptionsSetInDI_Compress()
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.NoCompression);
|
||||
services.AddResponseCompression(TextPlain);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseResponseCompression();
|
||||
app.Run(context =>
|
||||
{
|
||||
context.Response.Headers[HeaderNames.ContentMD5] = "MD5";
|
||||
context.Response.ContentType = TextPlain;
|
||||
return context.Response.WriteAsync(new string('a', 100));
|
||||
});
|
||||
});
|
||||
|
||||
var server = new TestServer(builder);
|
||||
var client = server.CreateClient();
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
request.Headers.AcceptEncoding.ParseAdd("gzip");
|
||||
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
CheckResponseCompressed(response, expectedBodyLength: 123);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData("text/plain2")]
|
||||
|
|
Загрузка…
Ссылка в новой задаче