Output caching should always vary by Accept-Encoding
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
When both response compression and output caching are enabled, it appears that ASP.NET Core caches the first encoding to be generated, then always returns content with that encoding.
### Expected Behavior
I expected each encoding to be cached separately so responses are correct while avoiding the overhead of compressing each response.
### Steps To Reproduce
This project has a simple repro:
https://github.com/jonpayne/AspNetCacheIssue/tree/main/src
Using this repro, if I first request the text file with Brotli compression, I get the expected result:
```bash
curl -s -D - https://localhost:5000/test.txt -H "Accept-Encoding: br" -o br.dat
```
```http
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Tue, 10 Jan 2023 05:33:16 GMT
Server: Kestrel
Accept-Ranges: bytes
Content-Encoding: br
ETag: "1d924af6fef9583"
Last-Modified: Tue, 10 Jan 2023 04:53:10 GMT
Transfer-Encoding: chunked
Vary: Accept-Encoding
```
But if I then request the same content with GZip compression, the response uses Brotli compression:
```bash
curl -s -D - https://localhost:5000/test.txt -H "Accept-Encoding: gzip" -o gzip.dat
```
```http
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Tue, 10 Jan 2023 05:33:16 GMT
Server: Kestrel
Accept-Ranges: bytes
Age: 9
Content-Encoding: br
ETag: "1d924af6fef9583"
Last-Modified: Tue, 10 Jan 2023 04:53:10 GMT
Transfer-Encoding: chunked
Vary: Accept-Encoding
```
### Exceptions (if any)
_No response_
### .NET Version
7.0.101
### Anything else?
I can work around this using this code:
```csharp
builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(builder =>
{
builder.SetVaryByQuery(string.Empty);
builder.VaryByValue(context =>
{
var responseCompressionProvider = context.RequestServices.GetService()!;
var encodingName = responseCompressionProvider.GetCompressionProvider(context)?.EncodingName ?? "none";
return new KeyValuePair("compression", encodingName);
});
builder.Cache();
});
});
```
While this works, it feels like something that should be provided by the framework.
Contributor guide
Assessment
This issue has not been assessed yet.