Asp.net core dotnet core 2 asp.net中特定于路由的响应压缩?

Asp.net core dotnet core 2 asp.net中特定于路由的响应压缩?,asp.net-core,.net-core,Asp.net Core,.net Core,这似乎有点毫无意义,但我希望我的一个API端点支持“最优”gzip压缩。对于所有其他人,我想要“无”或“最快” 这可能吗?我怎样才能做到这一点 最理想的情况是,我希望以某种方式从控制器操作中向服务指示我希望当前请求被gzip处理,以及使用什么设置 我想我可以尝试从ResponseCompressionMiddleware中提取Invoke方法,并将其转换为它自己的服务,但我想先看看是否有更简单的方法。好的,所以我花了太长时间来处理这个问题。这个答案是为了分享我是如何做到这一点的,但我不建议使用这

这似乎有点毫无意义,但我希望我的一个API端点支持“最优”gzip压缩。对于所有其他人,我想要“无”或“最快”

这可能吗?我怎样才能做到这一点

最理想的情况是,我希望以某种方式从控制器操作中向服务指示我希望当前请求被gzip处理,以及使用什么设置


我想我可以尝试从ResponseCompressionMiddleware中提取Invoke方法,并将其转换为它自己的服务,但我想先看看是否有更简单的方法。

好的,所以我花了太长时间来处理这个问题。这个答案是为了分享我是如何做到这一点的,但我不建议使用这种方法,希望有人能指出我错过的一种非常简单的方法

因此,在没有进一步告别的情况下,以下代码满足了我的需要:

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;
    }
}
类GZipAttribute:ResultFilterAttribute { 私有类响应压缩选项提供程序:IOOptions { 私有类GZIPCompressionProviderOptions提供程序:IOOptions { public gzip压缩提供程序选项提供程序(压缩级别压缩级别) { this.Value=new gzip压缩提供程序选项() { 水平=压缩水平 }; } public gzip压缩提供程序选项值{get;private set;} } 公共响应压缩选项提供程序(压缩级别) { this.Value=newresponsecompressionoptions() { EnableForHttps=true }; 添加(新的GzipCompressionProvider(新的GZIPCompressionProviderOptionProvider(级别)); } 公共响应压缩选项值{get;private set;} } 公共压缩级别压缩级别{get;private set;} public bool body containssecret{get;private set;} public bool BodyContainsFormInput{get;private set;} public gzip属性(压缩级别压缩级别,bool bodyContainsSecret=true,bool bodycontainsseformput=true) { 压缩水平=压缩水平; } 私有void logSkippingGzip(结果执行上下文ctxt,字符串原因) { ILogger=ctxt.HttpContext.RequestServices.GetService(); logger.LogWarning(“[GZip]跳过--”+原因); } ResultExecutionAsync上的公共重写异步任务(ResultExecutionContext executingContext,ResultExecutionDelegate next) { if(executingContext.HttpContext.Request.IsHttps&&BodyContainsFormInput&&BodyContainsSecret) { logSkippingGzip(executingContext,“请求为HTTPS,但端点未标记为不受漏洞攻击的影响”); 等待下一个(); } 其他的 等待新的ResponseCompressionMiddleware((上下文)=>{return next();},新的ResponseCompressionProvider(executingContext.HttpContext.RequestServices,新的ResponseCompressionOptionProvider(CompressionLevel))。调用(executingContext.HttpContext); 返回; } }
它现在似乎工作顺利,但我想要更简洁的东西。如果你们有其他想法,请告诉我。为了应用这一点,我只需在MVC控制器中的任何操作中添加一个
[GZip(CompressionLevel.Optimal)]

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

请参见此处的中间件过滤器属性:

Mvc有一个功能,您可以为特定的路由/控制器添加中间件。@这听起来很有希望。我现在将研究它。因此,我设法让它与@Tratcher的建议一起工作的唯一方法是在MVC调用中显式定义路由(我的所有其他路由都是使用属性定义的),然后为该路由分配一个特定的中间件。我不知道是否有其他方法可以从控制器中定义、启用/禁用中间件。想法?我认为这也有一个属性。中间件过滤器属性。