Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,18 @@ public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, Cancella
}

/// <summary>
/// Checks if the response should be compressed and sets the response headers.
/// Examines the response on first write to see if compression should be used and if true sets the Vary Accept-Encoding header.
/// </summary>
/// <returns>The compression provider to use if compression is enabled, otherwise null.</returns>
private ICompressionProvider? InitializeCompressionHeaders()
/// <param name="provider">current response compression provider</param>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <returns><see langword="true" /> if the response should be compressed, otherwise <see langword="false" />.</returns>
internal static bool ShouldCompressResponseCommon(IResponseCompressionProvider provider, HttpContext context)
{
if (_provider.ShouldCompressResponse(_context))
var result = provider.ShouldCompressResponse(context);

if (result)
{
var headers = _context.Response.Headers;
// If the MIME type indicates that the response could be compressed, caches will need to vary by the Accept-Encoding header
var headers = context.Response.Headers;
var varyValues = headers.GetCommaSeparatedValues(HeaderNames.Vary);
var varyByAcceptEncoding = false;

Expand All @@ -219,10 +222,22 @@ public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, Cancella

if (!varyByAcceptEncoding)
{
// Can't use += as StringValues does not override operator+
// and the implict conversions will cause an incorrect string concat https://github.com/dotnet/runtime/issues/52507
headers.Vary = StringValues.Concat(headers.Vary, HeaderNames.AcceptEncoding);
}
}

return result;
}

/// <summary>
/// Checks if the response should be compressed and sets the response headers.
/// </summary>
/// <returns>The compression provider to use if compression is enabled, otherwise null.</returns>
private ICompressionProvider? InitializeCompressionHeaders()
{
if (ShouldCompressResponseCommon(_provider, _context))
{
var headers = _context.Response.Headers;

var compressionProvider = ResolveCompressionProvider();
if (compressionProvider != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,19 @@ public Task Invoke(HttpContext context)
{
if (!_provider.CheckRequestAcceptsCompression(context))
{
var originalResponseFeature = context.Features.GetRequiredFeature<IHttpResponseFeature>();
originalResponseFeature.OnStarting(OnStartingResponseHandler, context);
return _next(context);
}
return InvokeCore(context);
}

private async Task OnStartingResponseHandler(object state)
{
HttpContext context = (HttpContext)state;
ResponseCompressionBody.ShouldCompressResponseCommon(_provider, context);
}

private async Task InvokeCore(HttpContext context)
{
var originalBodyFeature = context.Features.Get<IHttpResponseBodyFeature>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ public void Options_HttpsDisabledByDefault()
}

[Fact]
public async Task Request_NoAcceptEncoding_Uncompressed()
public async Task Request_NoAcceptEncoding_Uncompressed_WithVaryHeader()
{
var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: null, responseType: TextPlain);

CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: false);
AssertLog(logMessages.Single(), LogLevel.Debug, "No response compression available, the Accept-Encoding header is missing or invalid.");
CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: true);
Assert.Equal(2, logMessages.Count);
AssertLog(logMessages.First(), LogLevel.Debug, "No response compression available, the Accept-Encoding header is missing or invalid.");
AssertLog(logMessages.Skip(1).First(), LogLevel.Trace, "Response compression is available for this Content-Type.");
}

[Fact]
Expand Down Expand Up @@ -132,12 +134,14 @@ public async Task Request_AcceptUnknown_NotCompressed()
}

[Fact]
public async Task RequestHead_NoAcceptEncoding_Uncompressed()
public async Task RequestHead_NoAcceptEncoding_Uncompressed_WithVaryHeader()
{
var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: null, responseType: TextPlain, httpMethod: HttpMethods.Head);

CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: false);
AssertLog(logMessages.Single(), LogLevel.Debug, "No response compression available, the Accept-Encoding header is missing or invalid.");
CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: true);
Assert.Equal(2, logMessages.Count);
AssertLog(logMessages.First(), LogLevel.Debug, "No response compression available, the Accept-Encoding header is missing or invalid.");
AssertLog(logMessages.Skip(1).First(), LogLevel.Trace, "Response compression is available for this Content-Type.");
}

[Fact]
Expand Down
Loading