diff --git a/PolyShim.Tests/Net50/HttpClientTests.cs b/PolyShim.Tests/Net50/HttpClientTests.cs index cc799aa..f216b57 100644 --- a/PolyShim.Tests/Net50/HttpClientTests.cs +++ b/PolyShim.Tests/Net50/HttpClientTests.cs @@ -150,4 +150,72 @@ await httpClient.PatchAsync( ex.CancellationToken.Should().Be(cancellationToken); } + + [Fact] + public async Task CopyToAsync_Test() + { + // Arrange + using var content = new StringContent("Hello world!"); + using var stream = new MemoryStream(); + + // Act + await content.CopyToAsync(stream, CancellationToken.None); + 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 + using var content = new StringContent("Hello world!"); + using var stream = new MemoryStream(); + + // Act + await content.CopyToAsync(stream, context: null); + 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 9b315e5..df2f793 100644 --- a/Signatures.md +++ b/Signatures.md @@ -1,8 +1,8 @@ # Signatures -- **Total:** 608 +- **Total:** 610 - **Types:** 120 -- **Members:** 488 +- **Members:** 490 ___ @@ -249,6 +249,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