From 2f8a023b32cf92164fcf23d244434cd371b4beb1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 3 Oct 2026 12:06:08 +0000 Subject: [PATCH 1/3] Add HttpContent.CopyToAsync polyfills with CancellationToken Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- PolyShim.Tests/Net50/HttpClientTests.cs | 70 +++++++++++++++++++++++++ PolyShim/Net50/HttpContent.cs | 19 +++++++ Signatures.md | 6 ++- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/PolyShim.Tests/Net50/HttpClientTests.cs b/PolyShim.Tests/Net50/HttpClientTests.cs index cc799aa..2ab3ca5 100644 --- a/PolyShim.Tests/Net50/HttpClientTests.cs +++ b/PolyShim.Tests/Net50/HttpClientTests.cs @@ -150,4 +150,74 @@ await httpClient.PatchAsync( ex.CancellationToken.Should().Be(cancellationToken); } + + [Fact] + public async Task CopyToAsync_Test() + { + // Arrange + var cancellationToken = new CancellationToken(); + using var content = new StringContent("Hello world!"); + using var stream = new MemoryStream(); + + // Act + await content.CopyToAsync(stream, cancellationToken); + stream.Position = 0; + + using var reader = new StreamReader(stream); + var result = await reader.ReadToEndAsync(); + + // Assert + result.Should().Be("Hello world!"); + } + + [Fact] + public async Task CopyToAsync_Cancellation_Test() + { + // Arrange + var cancellationToken = new CancellationToken(true); + using var content = new StringContent("Hello world!"); + using var stream = new MemoryStream(); + + // Act & assert + var ex = await Assert.ThrowsAnyAsync(async () => + await content.CopyToAsync(stream, cancellationToken) + ); + + ex.CancellationToken.Should().Be(cancellationToken); + } + + [Fact] + public async Task CopyToAsync_WithTransportContext_Test() + { + // Arrange + var cancellationToken = new CancellationToken(); + using var content = new StringContent("Hello world!"); + using var stream = new MemoryStream(); + + // Act + await content.CopyToAsync(stream, context: null, cancellationToken); + stream.Position = 0; + + using var reader = new StreamReader(stream); + var result = await reader.ReadToEndAsync(); + + // Assert + result.Should().Be("Hello world!"); + } + + [Fact] + public async Task CopyToAsync_WithTransportContext_Cancellation_Test() + { + // Arrange + var cancellationToken = new CancellationToken(true); + using var content = new StringContent("Hello world!"); + using var stream = new MemoryStream(); + + // Act & assert + var ex = await Assert.ThrowsAnyAsync(async () => + await content.CopyToAsync(stream, context: null, cancellationToken) + ); + + ex.CancellationToken.Should().Be(cancellationToken); + } } diff --git a/PolyShim/Net50/HttpContent.cs b/PolyShim/Net50/HttpContent.cs index 56c2d6e..21b7f4c 100644 --- a/PolyShim/Net50/HttpContent.cs +++ b/PolyShim/Net50/HttpContent.cs @@ -5,6 +5,7 @@ #pragma warning disable CS0436 using System.IO; +using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -39,6 +40,24 @@ public async Task ReadAsStringAsync(CancellationToken cancellationToken cancellationToken.ThrowIfCancellationRequested(); return await httpContent.ReadAsStringAsync().ConfigureAwait(false); } + + // https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.copytoasync#system-net-http-httpcontent-copytoasync(system-io-stream-system-threading-cancellationtoken) + public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + await httpContent.CopyToAsync(stream).ConfigureAwait(false); + } + + // https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.copytoasync#system-net-http-httpcontent-copytoasync(system-io-stream-system-net-transportcontext-system-threading-cancellationtoken) + public async Task CopyToAsync( + Stream stream, + TransportContext? context, + CancellationToken cancellationToken = default + ) + { + cancellationToken.ThrowIfCancellationRequested(); + await httpContent.CopyToAsync(stream, context).ConfigureAwait(false); + } } #endif } diff --git a/Signatures.md b/Signatures.md index ee17165..0326fac 100644 --- a/Signatures.md +++ b/Signatures.md @@ -1,8 +1,8 @@ # Signatures -- **Total:** 601 +- **Total:** 603 - **Types:** 119 -- **Members:** 482 +- **Members:** 484 ___ @@ -247,6 +247,8 @@ ___ - [`Task GetStringAsync(string, CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpclient.getstringasync#system-net-http-httpclient-getstringasync(system-string-system-threading-cancellationtoken)) .NET 5.0 - [`Task GetStringAsync(Uri, CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpclient.getstringasync#system-net-http-httpclient-getstringasync(system-uri-system-threading-cancellationtoken)) .NET 5.0 - `HttpContent` + - [`Task CopyToAsync(Stream, CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.copytoasync#system-net-http-httpcontent-copytoasync(system-io-stream-system-threading-cancellationtoken)) .NET 5.0 + - [`Task CopyToAsync(Stream, TransportContext?, CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.copytoasync#system-net-http-httpcontent-copytoasync(system-io-stream-system-net-transportcontext-system-threading-cancellationtoken)) .NET 5.0 - [`Task ReadAsByteArrayAsync(CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.readasbytearrayasync#system-net-http-httpcontent-readasbytearrayasync(system-threading-cancellationtoken)) .NET 5.0 - [`Task ReadAsStreamAsync(CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.readasstreamasync#system-net-http-httpcontent-readasstreamasync(system-threading-cancellationtoken)) .NET 5.0 - [`Task ReadAsStringAsync(CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.net.http.httpcontent.readasstringasync#system-net-http-httpcontent-readasstringasync(system-threading-cancellationtoken)) .NET 5.0 From 0aaaa13c65bedf173de83616602a577b6ceb3a8d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 3 Oct 2026 12:17:04 +0000 Subject: [PATCH 2/3] Remove unnecessary cancellation tokens in non-cancellation CopyToAsync tests Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- PolyShim.Tests/Net50/HttpClientTests.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/PolyShim.Tests/Net50/HttpClientTests.cs b/PolyShim.Tests/Net50/HttpClientTests.cs index 2ab3ca5..f669965 100644 --- a/PolyShim.Tests/Net50/HttpClientTests.cs +++ b/PolyShim.Tests/Net50/HttpClientTests.cs @@ -155,12 +155,11 @@ await httpClient.PatchAsync( public async Task CopyToAsync_Test() { // Arrange - var cancellationToken = new CancellationToken(); using var content = new StringContent("Hello world!"); using var stream = new MemoryStream(); // Act - await content.CopyToAsync(stream, cancellationToken); + await content.CopyToAsync(stream); stream.Position = 0; using var reader = new StreamReader(stream); @@ -190,12 +189,11 @@ await content.CopyToAsync(stream, cancellationToken) public async Task CopyToAsync_WithTransportContext_Test() { // Arrange - var cancellationToken = new CancellationToken(); using var content = new StringContent("Hello world!"); using var stream = new MemoryStream(); // Act - await content.CopyToAsync(stream, context: null, cancellationToken); + await content.CopyToAsync(stream, context: null); stream.Position = 0; using var reader = new StreamReader(stream); From 8b0e3e5f179f2569388c52ae5740e6cfde95b4e7 Mon Sep 17 00:00:00 2001 From: Oleksii Holub <1935960+Tyrrrz@users.noreply.github.com> Date: Sat, 3 Oct 2026 15:28:21 +0300 Subject: [PATCH 3/3] Add CancellationToken to CopyToAsync method Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- PolyShim.Tests/Net50/HttpClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PolyShim.Tests/Net50/HttpClientTests.cs b/PolyShim.Tests/Net50/HttpClientTests.cs index f669965..f216b57 100644 --- a/PolyShim.Tests/Net50/HttpClientTests.cs +++ b/PolyShim.Tests/Net50/HttpClientTests.cs @@ -159,7 +159,7 @@ public async Task CopyToAsync_Test() using var stream = new MemoryStream(); // Act - await content.CopyToAsync(stream); + await content.CopyToAsync(stream, CancellationToken.None); stream.Position = 0; using var reader = new StreamReader(stream);