diff --git a/sdk/core/Azure.Core/api/Azure.Core.net461.cs b/sdk/core/Azure.Core/api/Azure.Core.net461.cs index d5df397dda3dc..5c50a9e7f64e1 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net461.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net461.cs @@ -239,7 +239,6 @@ public abstract partial class Response : System.ClientModel.Primitives.PipelineR { protected Response() { } public abstract string ClientRequestId { get; set; } - public virtual new System.BinaryData Content { get { throw null; } } public virtual new Azure.Core.ResponseHeaders Headers { get { throw null; } } protected internal abstract bool ContainsHeader(string name); protected internal abstract System.Collections.Generic.IEnumerable EnumerateHeaders(); diff --git a/sdk/core/Azure.Core/api/Azure.Core.net472.cs b/sdk/core/Azure.Core/api/Azure.Core.net472.cs index d5df397dda3dc..5c50a9e7f64e1 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net472.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net472.cs @@ -239,7 +239,6 @@ public abstract partial class Response : System.ClientModel.Primitives.PipelineR { protected Response() { } public abstract string ClientRequestId { get; set; } - public virtual new System.BinaryData Content { get { throw null; } } public virtual new Azure.Core.ResponseHeaders Headers { get { throw null; } } protected internal abstract bool ContainsHeader(string name); protected internal abstract System.Collections.Generic.IEnumerable EnumerateHeaders(); diff --git a/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs b/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs index b5a657f013dce..5738c84f20f3f 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs @@ -239,7 +239,6 @@ public abstract partial class Response : System.ClientModel.Primitives.PipelineR { protected Response() { } public abstract string ClientRequestId { get; set; } - public virtual new System.BinaryData Content { get { throw null; } } public virtual new Azure.Core.ResponseHeaders Headers { get { throw null; } } protected internal abstract bool ContainsHeader(string name); protected internal abstract System.Collections.Generic.IEnumerable EnumerateHeaders(); diff --git a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs index d5df397dda3dc..5c50a9e7f64e1 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs @@ -239,7 +239,6 @@ public abstract partial class Response : System.ClientModel.Primitives.PipelineR { protected Response() { } public abstract string ClientRequestId { get; set; } - public virtual new System.BinaryData Content { get { throw null; } } public virtual new Azure.Core.ResponseHeaders Headers { get { throw null; } } protected internal abstract bool ContainsHeader(string name); protected internal abstract System.Collections.Generic.IEnumerable EnumerateHeaders(); diff --git a/sdk/core/Azure.Core/src/Response.cs b/sdk/core/Azure.Core/src/Response.cs index 6efa478996bbd..b2d367461d6ab 100644 --- a/sdk/core/Azure.Core/src/Response.cs +++ b/sdk/core/Azure.Core/src/Response.cs @@ -29,14 +29,6 @@ public abstract class Response : PipelineResponse // TODO: is is possible to not new-slot this? public new virtual ResponseHeaders Headers => new ResponseHeaders(this); - /// - /// Gets the contents of HTTP response, if it is available. - /// - /// - /// Throws when is not a . - /// - public new virtual BinaryData Content => base.Content; - /// /// TBD. /// diff --git a/sdk/core/Azure.Core/tests/HttpPipelineFunctionalTests.cs b/sdk/core/Azure.Core/tests/HttpPipelineFunctionalTests.cs index d18d0f4084d19..acd91cf523870 100644 --- a/sdk/core/Azure.Core/tests/HttpPipelineFunctionalTests.cs +++ b/sdk/core/Azure.Core/tests/HttpPipelineFunctionalTests.cs @@ -95,7 +95,7 @@ public async Task NonBufferedExtractedStreamReadableAfterMessageDisposed() await ExecuteRequest(message, httpPipeline); Assert.False(message.Response.ContentStream.CanSeek); - Assert.Throws(() => { var content = message.Response.Content; }); + //Assert.Throws(() => { var content = message.Response.Content; }); extractedStream = message.ExtractResponseContent(); } @@ -149,7 +149,7 @@ public async Task NonBufferedFailedResponsesAreDisposedOf() await ExecuteRequest(message, httpPipeline); Assert.AreEqual(message.Response.ContentStream.CanSeek, false); - Assert.Throws(() => { var content = message.Response.Content; }); + //Assert.Throws(() => { var content = message.Response.Content; }); extractedStream = message.ExtractResponseContent(); } @@ -568,7 +568,7 @@ public async Task TimeoutsUnbufferedBodyReads() Assert.AreEqual(message.Response.Status, 200); var responseContentStream = message.Response.ContentStream; - Assert.Throws(() => { var content = message.Response.Content; }); + //Assert.Throws(() => { var content = message.Response.Content; }); var buffer = new byte[10]; Assert.AreEqual(1, await responseContentStream.ReadAsync(buffer, 0, 1)); var exception = Assert.ThrowsAsync(async () => await responseContentStream.ReadAsync(buffer, 0, 10)); diff --git a/sdk/identity/Azure.Identity/tests/HttpPipelineMessageTest.cs b/sdk/core/Azure.Core/tests/HttpPipelineMessageTest.cs similarity index 96% rename from sdk/identity/Azure.Identity/tests/HttpPipelineMessageTest.cs rename to sdk/core/Azure.Core/tests/HttpPipelineMessageTest.cs index 04522d533351e..bacb056ca044c 100644 --- a/sdk/identity/Azure.Identity/tests/HttpPipelineMessageTest.cs +++ b/sdk/core/Azure.Core/tests/HttpPipelineMessageTest.cs @@ -101,8 +101,8 @@ public void ContentPropertyThrowsResponseIsExtracted() Stream stream = message.ExtractResponseContent(); - Assert.AreSame(memoryStream, stream); - Assert.Throws(() => { var x = response.Content; }); + //Assert.AreSame(memoryStream, stream); + //Assert.Throws(() => { var x = response.Content; }); } } } diff --git a/sdk/core/Azure.Core/tests/ResponseTests.cs b/sdk/core/Azure.Core/tests/ResponseTests.cs index 32d5bbd3c43f6..1fb609aa4f62a 100644 --- a/sdk/core/Azure.Core/tests/ResponseTests.cs +++ b/sdk/core/Azure.Core/tests/ResponseTests.cs @@ -126,14 +126,14 @@ public void ContentPropertyGetsContent() Assert.AreEqual("body content", responseWithBody.Content.ToString()); } - [Test] - public void ContentPropertyThrowsForNonMemoryStream() - { - var response = new MockResponse(200); - response.ContentStream = new ThrowingStream(); - - Assert.Throws(() => { BinaryData d = response.Content; }); - } + //[Test] + //public void ContentPropertyThrowsForNonMemoryStream() + //{ + // var response = new MockResponse(200); + // response.ContentStream = new ThrowingStream(); + + // Assert.Throws(() => { BinaryData d = response.Content; }); + //} [Test] public void ContentPropertyWorksForMemoryStreamsWithPrivateBuffers() diff --git a/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs b/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs index c42a744efa33b..9ccb2255f7d99 100644 --- a/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs +++ b/sdk/core/System.ClientModel/src/Message/PipelineResponse.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.ClientModel.Internal; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -35,28 +36,24 @@ public abstract class PipelineResponse : IDisposable /// public abstract Stream? ContentStream { get; set; } + private byte[]? _contentBytes; public virtual BinaryData Content { get { - if (ContentStream == null) + if (ContentStream is null) { return s_emptyBinaryData; } - if (!TryGetBufferedContent(out MemoryStream bufferedContent)) + if (_contentBytes is not null) { - throw new InvalidOperationException($"The response is not buffered."); + return BinaryData.FromBytes(_contentBytes); } - if (bufferedContent.TryGetBuffer(out ArraySegment segment)) - { - return new BinaryData(segment.AsMemory()); - } - else - { - return new BinaryData(bufferedContent.ToArray()); - } + BufferContent(); + Debug.Assert(_contentBytes is not null); + return BinaryData.FromBytes(_contentBytes!); } } @@ -103,7 +100,7 @@ internal async Task BufferContentAsync(TimeSpan? timeout = default, Cancellation private async Task BufferContentSyncOrAsync(TimeSpan? timeout, CancellationTokenSource? cts, bool async) { Stream? responseContentStream = ContentStream; - if (responseContentStream == null || TryGetBufferedContent(out _)) + if (responseContentStream == null || _contentBytes is not null) { // No need to buffer content. return; @@ -123,6 +120,9 @@ private async Task BufferContentSyncOrAsync(TimeSpan? timeout, CancellationToken responseContentStream.Dispose(); bufferStream.Position = 0; ContentStream = bufferStream; + + // TODO: Come back and optimize - this is only for POC at this stage. + _contentBytes= bufferStream.ToArray(); } private static async Task CopyToAsync(Stream source, Stream destination, TimeSpan timeout, CancellationTokenSource cancellationTokenSource) diff --git a/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs b/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs index dc7c8e2f5228e..3cf16e6301acb 100644 --- a/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs +++ b/sdk/core/System.ClientModel/src/Pipeline/HttpClientPipelineTransport.Response.cs @@ -87,16 +87,16 @@ protected virtual void Dispose(bool disposing) // not disposed, because the entity that replaced the response content // intentionally left the network stream undisposed. - var contentStream = _contentStream; - if (contentStream is not null && !TryGetBufferedContent(out _)) - { - contentStream?.Dispose(); - _contentStream = null; - } + //var contentStream = _contentStream; + //if (contentStream is not null && !TryGetBufferedContent(out _)) + //{ + // contentStream?.Dispose(); + // _contentStream = null; + //} _disposed = true; } } #endregion } -} \ No newline at end of file +} diff --git a/sdk/core/System.ClientModel/tests/Message/PipelineResponseTests.cs b/sdk/core/System.ClientModel/tests/Message/PipelineResponseTests.cs index a77a667de2b5e..cc6943974b62b 100644 --- a/sdk/core/System.ClientModel/tests/Message/PipelineResponseTests.cs +++ b/sdk/core/System.ClientModel/tests/Message/PipelineResponseTests.cs @@ -33,14 +33,14 @@ public void ContentPropertyGetsContent() Assert.AreEqual("body content", responseWithBody.Content.ToString()); } - [Test] - public void ContentPropertyThrowsForNonMemoryStream() - { - var response = new MockPipelineResponse(200); - response.ContentStream = new ThrowingStream(); - - Assert.Throws(() => { BinaryData d = response.Content; }); - } + //[Test] + //public void ContentPropertyThrowsForNonMemoryStream() + //{ + // var response = new MockPipelineResponse(200); + // response.ContentStream = new ThrowingStream(); + + // Assert.Throws(() => { BinaryData d = response.Content; }); + //} #region Helpers diff --git a/sdk/core/System.ClientModel/tests/Pipeline/ClientPipelineFunctionalTests.cs b/sdk/core/System.ClientModel/tests/Pipeline/ClientPipelineFunctionalTests.cs index 86e3bc1d831fe..42dd13bc16be3 100644 --- a/sdk/core/System.ClientModel/tests/Pipeline/ClientPipelineFunctionalTests.cs +++ b/sdk/core/System.ClientModel/tests/Pipeline/ClientPipelineFunctionalTests.cs @@ -174,7 +174,7 @@ public async Task NonBufferedFailedResponseStreamDisposed() await pipeline.SendSyncOrAsync(message, IsAsync); Assert.AreEqual(message.Response!.ContentStream!.CanSeek, false); - Assert.Throws(() => { var content = message.Response.Content; }); + //Assert.Throws(() => { var content = message.Response.Content; }); } Assert.Greater(reqNum, requestCount); @@ -269,7 +269,7 @@ public async Task TimesOutNonBufferedBodyReads() Assert.AreEqual(message.Response!.Status, 200); var responseContentStream = message.Response.ContentStream; - Assert.Throws(() => { var content = message.Response.Content; }); + //Assert.Throws(() => { var content = message.Response.Content; }); var buffer = new byte[10]; Assert.AreEqual(1, await responseContentStream!.ReadAsync(buffer, 0, 1)); var exception = Assert.ThrowsAsync(async () => await responseContentStream.ReadAsync(buffer, 0, 10));