public async Task Invoke(HttpContext httpContext)
        {
            var originalResponseBody = httpContext.Response.Body;

            // no-op if buffering is already available.
            if (originalResponseBody.CanSeek)
            {
                await _next(httpContext);

                return;
            }

            var originalBufferingFeature = httpContext.Features.Get <IHttpBufferingFeature>();
            var originalSendFileFeature  = httpContext.Features.Get <IHttpSendFileFeature>();

            try
            {
                // Shim the response stream
                var bufferStream = new BufferingWriteStream(originalResponseBody);
                httpContext.Response.Body = bufferStream;
                httpContext.Features.Set <IHttpBufferingFeature>(new HttpBufferingFeature(bufferStream, originalBufferingFeature));
                if (originalSendFileFeature != null)
                {
                    httpContext.Features.Set <IHttpSendFileFeature>(new SendFileFeatureWrapper(originalSendFileFeature, bufferStream));
                }

                await _next(httpContext);

                // If we're still buffered, set the content-length header and flush the buffer.
                // Only if the content-length header is not already set, and some content was buffered.
                if (!httpContext.Response.HasStarted && bufferStream.CanSeek && bufferStream.Length > 0)
                {
                    if (!httpContext.Response.ContentLength.HasValue)
                    {
                        httpContext.Response.Headers["X-Decompressed-Content-Length"] = bufferStream.Length.ToString();
                    }
                    await bufferStream.FlushAsync();
                }
            }
            finally
            {
                // undo everything
                httpContext.Features.Set(originalBufferingFeature);
                httpContext.Features.Set(originalSendFileFeature);
                httpContext.Response.Body = originalResponseBody;
            }
        }
 public SendFileFeatureWrapper(IHttpSendFileFeature originalSendFileFeature, BufferingWriteStream bufferStream)
 {
     _originalSendFileFeature = originalSendFileFeature;
     _bufferStream            = bufferStream;
 }
 internal HttpBufferingFeature(BufferingWriteStream buffer, IHttpBufferingFeature innerFeature)
 {
     _buffer       = buffer;
     _innerFeature = innerFeature;
 }