From d68116240a814f8ab3e0dc1efbda6d22418dce06 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 23 Jan 2026 08:57:49 +0000
Subject: [PATCH 1/6] Initial plan
From c4db1e4b199d513d71d67e42e40030819a4a3c79 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 23 Jan 2026 09:04:39 +0000
Subject: [PATCH 2/6] Add DecompressionMethods.Zstandard enum and handler
support
Co-authored-by: rzikm <32671551+rzikm@users.noreply.github.com>
---
.../DecompressionHandler.cs | 20 ++++++++++++++++++-
.../SocketsHttpHandler/SocketsHttpHandler.cs | 2 +-
.../ref/System.Net.Primitives.cs | 1 +
.../src/System/Net/DecompressionMethods.cs | 1 +
4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs
index c0e15763b53db6..6a3ab852ca3fe1 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs
@@ -19,9 +19,11 @@ internal sealed class DecompressionHandler : HttpMessageHandlerStage
private const string Gzip = "gzip";
private const string Deflate = "deflate";
private const string Brotli = "br";
+ private const string Zstd = "zstd";
private static readonly StringWithQualityHeaderValue s_gzipHeaderValue = new(Gzip);
private static readonly StringWithQualityHeaderValue s_deflateHeaderValue = new(Deflate);
private static readonly StringWithQualityHeaderValue s_brotliHeaderValue = new(Brotli);
+ private static readonly StringWithQualityHeaderValue s_zstdHeaderValue = new(Zstd);
/// Header value for all enabled decompression methods, e.g. "gzip, deflate".
private readonly string _acceptEncodingHeaderValue;
@@ -34,7 +36,7 @@ public DecompressionHandler(DecompressionMethods decompressionMethods, HttpMessa
_decompressionMethods = decompressionMethods;
_innerHandler = innerHandler;
- List methods = [GZipEnabled ? Gzip : null, DeflateEnabled ? Deflate : null, BrotliEnabled ? Brotli : null];
+ List methods = [GZipEnabled ? Gzip : null, DeflateEnabled ? Deflate : null, BrotliEnabled ? Brotli : null, ZstandardEnabled ? Zstd : null];
methods.RemoveAll(item => item is null);
_acceptEncodingHeaderValue = string.Join(", ", methods);
}
@@ -42,6 +44,7 @@ public DecompressionHandler(DecompressionMethods decompressionMethods, HttpMessa
internal bool GZipEnabled => (_decompressionMethods & DecompressionMethods.GZip) != 0;
internal bool DeflateEnabled => (_decompressionMethods & DecompressionMethods.Deflate) != 0;
internal bool BrotliEnabled => (_decompressionMethods & DecompressionMethods.Brotli) != 0;
+ internal bool ZstandardEnabled => (_decompressionMethods & DecompressionMethods.Zstandard) != 0;
private static bool EncodingExists(HttpHeaderValueCollection acceptEncodingHeader, string encoding)
{
@@ -81,6 +84,11 @@ internal override async ValueTask SendAsync(HttpRequestMess
{
acceptEncoding.Add(s_brotliHeaderValue);
}
+
+ if (ZstandardEnabled && !EncodingExists(acceptEncoding, Zstd))
+ {
+ acceptEncoding.Add(s_zstdHeaderValue);
+ }
}
HttpResponseMessage response = await _innerHandler.SendAsync(request, async, cancellationToken).ConfigureAwait(false);
@@ -105,6 +113,10 @@ internal override async ValueTask SendAsync(HttpRequestMess
{
response.Content = new BrotliDecompressedContent(response.Content, encodings);
}
+ else if (ZstandardEnabled && string.Equals(last, Zstd, StringComparison.OrdinalIgnoreCase))
+ {
+ response.Content = new ZstandardDecompressedContent(response.Content, encodings);
+ }
}
return response;
@@ -430,5 +442,11 @@ private sealed class BrotliDecompressedContent(HttpContent originalContent, stri
protected override Stream GetDecompressedStream(Stream originalStream) =>
new BrotliStream(originalStream, CompressionMode.Decompress);
}
+
+ private sealed class ZstandardDecompressedContent(HttpContent originalContent, string[] contentEncodings) : DecompressedContent(originalContent, contentEncodings)
+ {
+ protected override Stream GetDecompressedStream(Stream originalStream) =>
+ new ZstandardStream(originalStream, CompressionMode.Decompress);
+ }
}
}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs
index cd27280882608f..94a3043e913aeb 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs
@@ -569,7 +569,7 @@ private void EnsureDecompressionHandlerFactory()
}
// Not stored as a constant on the DecompressionHandler to allow it to get trimmed.
- private const DecompressionMethods SupportedDecompressionMethods = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli;
+ private const DecompressionMethods SupportedDecompressionMethods = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli | DecompressionMethods.Zstandard;
protected internal override HttpResponseMessage Send(HttpRequestMessage request,
CancellationToken cancellationToken)
diff --git a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
index d49a06959511db..4374afe3b2a9f8 100644
--- a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
+++ b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
@@ -120,6 +120,7 @@ public enum DecompressionMethods
GZip = 1,
Deflate = 2,
Brotli = 4,
+ Zstandard = 8,
}
public partial class DnsEndPoint : System.Net.EndPoint
{
diff --git a/src/libraries/System.Net.Primitives/src/System/Net/DecompressionMethods.cs b/src/libraries/System.Net.Primitives/src/System/Net/DecompressionMethods.cs
index 5523929dc46dfa..846c87d46d00ff 100644
--- a/src/libraries/System.Net.Primitives/src/System/Net/DecompressionMethods.cs
+++ b/src/libraries/System.Net.Primitives/src/System/Net/DecompressionMethods.cs
@@ -10,6 +10,7 @@ public enum DecompressionMethods
GZip = 0x1,
Deflate = 0x2,
Brotli = 0x4,
+ Zstandard = 0x8,
All = ~None
}
}
From 144e38083f2aa050f0175ba2c63294cba781afad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 23 Jan 2026 09:06:11 +0000
Subject: [PATCH 3/6] Add Zstandard decompression tests
Co-authored-by: rzikm <32671551+rzikm@users.noreply.github.com>
---
.../HttpClientHandlerTest.Decompression.cs | 31 +++++++++++++++++--
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs
index f45206e9941dfe..02724599c120ee 100644
--- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs
+++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs
@@ -28,7 +28,7 @@ public abstract class HttpClientHandler_Decompression_Test : HttpClientHandlerTe
public HttpClientHandler_Decompression_Test(ITestOutputHelper output) : base(output) { }
public static IEnumerable