路由Dotnet Core 2 ASP .NET中的特定响应压缩



这似乎有些毫无意义,但是我希望我的一个API端点支持"最佳" GZIP压缩。对于所有其他我想要的"无"或"最快"。

这可能吗?我该如何实现?

最佳地,我想以某种方式从控制器操作中向服务表示我希望当前请求被gzz和使用哪些设置的服务。

我以为我可以尝试从响应式压缩middleware的命令中汲取方法,并将其添加到自己的服务中,但是我想看看是否有更简单的东西。

因此,使用acpnetcore的注释提及的是通过 MiddlewareFilterAttribute作为路由特定的 Middleware作为路由的 CC_1,但没有提供实际的实际实施...

这是一种优雅的方法,可以使用开箱即用的响应压缩中间件仅使用几行代码来使用它。。。

在启动/program.cs中,您必须为开箱即用的响应压缩中间件依赖项设置DI:

builder.Services.AddResponseCompression(options => options.EnableForHttps = true);

然后添加一个封装它的新属性,使您在每个端点处的注释代码都可以简化,因此只能在一个地方进行增强:

using Microsoft.AspNetCore.Mvc;
public class EnableRouteResponseCompressionAttribute : MiddlewareFilterAttribute
{
    public EnableRouteResponseCompressionAttribute () 
        : base(typeof(EnableRouteResponseCompressionAttribute ))
    { }
    public void Configure(IApplicationBuilder applicationBuilder) 
        => applicationBuilder.UseResponseCompression();
}

现在您可以简单地使用它:

[Route("get-some-compressed-data")]
[HttpGet]
[EnableRouteResponseCompression] //<== The Magic is Here!
public async Task<Data> GetSomeCompressedData()
{
    // . . . get the data . . . 
}

好的,所以我玩了太久了。这个答案是分享我如何设法使它起作用,但我不建议这种方法,希望有人可以指出我错过的一种非常简单的方式。

因此,没有进一步的ADIEU,以下代码适合我的需求:

class GZipAttribute : ResultFilterAttribute
{
    private class ResponseCompressionOptionsProvider : IOptions<ResponseCompressionOptions>
    {
        private class GZipCompressionProviderOptionsProvider : IOptions<GzipCompressionProviderOptions>
        {
            public GZipCompressionProviderOptionsProvider(CompressionLevel compressionLevel)
            {
                this.Value = new GzipCompressionProviderOptions()
                {
                    Level = compressionLevel
                };
            }
            public GzipCompressionProviderOptions Value { get; private set; }
        }
        public ResponseCompressionOptionsProvider(CompressionLevel level)
        {
            this.Value = new ResponseCompressionOptions()
            {
                EnableForHttps = true
            };
            this.Value.Providers.Add(new GzipCompressionProvider(new GZipCompressionProviderOptionsProvider(level)));
        }
        public ResponseCompressionOptions Value { get; private set; }
    }
    public CompressionLevel CompressionLevel { get; private set; }
    public bool BodyContainsSecret { get; private set; }
    public bool BodyContainsFormInput { get; private set; }
    public GZipAttribute(CompressionLevel compressionLevel, bool bodyContainsSecret = true, bool bodyContainsFormInput = true)
    {
        CompressionLevel = compressionLevel;
    }
    private void logSkippingGzip(ResultExecutingContext ctxt, string reason)
    {
        ILogger logger = ctxt.HttpContext.RequestServices.GetService<ILogger>();
        logger.LogWarning("[GZip] SKIPPED -- " + reason);
    }
    public override async Task OnResultExecutionAsync(ResultExecutingContext executingContext, ResultExecutionDelegate next)
    {
        if (executingContext.HttpContext.Request.IsHttps && BodyContainsFormInput && BodyContainsSecret)
        {
            logSkippingGzip(executingContext, "Request is HTTPS but endpoint is not marked as being impervious to BREACH exploit.");
            await next();
        }
        else
            await new ResponseCompressionMiddleware((context) => { return next(); }, new ResponseCompressionProvider(executingContext.HttpContext.RequestServices, new ResponseCompressionOptionsProvider(CompressionLevel))).Invoke(executingContext.HttpContext);
        return;
    }
}

现在似乎可以游泳,但我想要更简洁的东西。如果你们/女孩还有其他想法,请告诉我。要应用此功能,我只需将[GZip(CompressionLevel.Optimal)]添加到我的MVC控制器中的任何操作中。

MVC具有一个功能,您可以在其中为特定路由/控制器添加中间件。

请参阅此处的中间件过滤器属性:https://blogs.msdn.microsoft.com/webdev/2016/11/16/announcing-asp-net-core-1/

最新更新