Description
Background and motivation
Currently, HttpClient
uses HttpCompletionOption.ResponseContentRead
as the default option:
This can simplify some logic of consumers, for example cancellation and duplex buffering can be handled at once.
When ResponseHeadersRead
is desired, for example passing the content stream to some parser or image control that supports incremental loading, there are only a limited members available. Importantly, the most-convenient GetStreamAsync
method doesn't accept HttpCompletionOption
. The streaming json helpers are explicitly specifying ResponseHeadersRead
:
API Proposal
namespace System.Net.Http;
public class HttpClient
{
public Task<Stream> GetStreamAsync([StringSyntax("Uri")] string? requestUri);
public Task<Stream> GetStreamAsync([StringSyntax("Uri")] string? requestUri, CancellationToken cancellationToken);
+ public Task<Stream> GetStreamAsync([StringSyntax("Uri")] string? requestUri, HttpCompletionOption completionOption);
+ public Task<Stream> GetStreamAsync([StringSyntax("Uri")] string? requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
public Task<Stream> GetStreamAsync(Uri? requestUri);
public Task<Stream> GetStreamAsync(Uri? requestUri, CancellationToken cancellationToken);
+ public Task<Stream> GetStreamAsync(Uri? requestUri, HttpCompletionOption completionOption);
+ public Task<Stream> GetStreamAsync(Uri? requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
+ public HttpCompletionOptions DefaultCompletionOptions { get; set; }
}
API Usage
using var httpClient = httpClientFactory.GetClient();
var imaTeapot = httpClient.GetStreamAsync("https://http.cat/images/418.jpg", HttpCompletionOption.ResponseHeadersRead);
imageControl.SetSourceStream(imaTeapot);
Alternative Designs
Are the overloads redundant? Can they be combined with CancellationToken cancellationToken = default
?
Risks
Allow specifying DefaultCompletionOptions
may have unintended effects for callers having assumptions for ResponseContentRead
. We can choose to only expose the completion options on individual methods. The CanSeek
property for content stream is changed.
This also increases the risk of using ResponseHeadersRead
inappropriately. Per testing, if the HttpClient
is disposed before the stream is read, the response stream will be effectively "detached" and become empty. I didn't find explicit mentions about this at https://learn.microsoft.com/dotnet/fundamentals/runtime-libraries/system-net-http-httpclient#buffering-and-request-lifetime.