<PackageReference Include="System.ClientModel" Version="1.1.0" />

HttpClientPipelineTransport

An implementation of PipelineTransport that uses a HttpClient to send and receive HTTP requests and responses.
using System.ClientModel.Internal; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace System.ClientModel.Primitives { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class HttpClientPipelineTransport : PipelineTransport, IDisposable { [System.Runtime.CompilerServices.Nullable(0)] private class HttpPipelineRequest : PipelineRequest { [System.Runtime.CompilerServices.Nullable(0)] private sealed class MessageBodyAdapter : HttpContent { private readonly BinaryContent _content; private readonly CancellationToken _cancellationToken; public MessageBodyAdapter(BinaryContent content, CancellationToken cancellationToken) { Argument.AssertNotNull(content, "content"); _content = content; _cancellationToken = cancellationToken; } [AsyncStateMachine(typeof(<SerializeToStreamAsync>d__3))] protected override Task SerializeToStreamAsync(Stream stream, [System.Runtime.CompilerServices.Nullable(2)] TransportContext context) { <SerializeToStreamAsync>d__3 stateMachine = default(<SerializeToStreamAsync>d__3); stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.stream = stream; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } protected override bool TryComputeLength(out long length) { return _content.TryComputeLength(out length); } } private const string AuthorizationHeaderName = "Authorization"; private string _method; [System.Runtime.CompilerServices.Nullable(2)] private Uri _uri; [System.Runtime.CompilerServices.Nullable(2)] private BinaryContent _content; private readonly PipelineRequestHeaders _headers; private bool _disposed; private static readonly HttpMethod _patchMethod = new HttpMethod("PATCH"); protected override string MethodCore { get { return _method; } set { Argument.AssertNotNull(value, "value"); _method = value; } } [System.Runtime.CompilerServices.Nullable(2)] protected override Uri UriCore { [System.Runtime.CompilerServices.NullableContext(2)] get { return _uri; } [System.Runtime.CompilerServices.NullableContext(2)] set { Argument.AssertNotNull(value, "value"); _uri = value; } } [System.Runtime.CompilerServices.Nullable(2)] protected override BinaryContent ContentCore { [System.Runtime.CompilerServices.NullableContext(2)] get { return _content; } [System.Runtime.CompilerServices.NullableContext(2)] set { _content = value; } } protected override PipelineRequestHeaders HeadersCore => _headers; protected internal HttpPipelineRequest() { _method = HttpMethod.Get.Method; _headers = new ArrayBackedRequestHeaders(); } private static HttpMethod ToHttpMethod(string method) { if (method == "GET") return HttpMethod.Get; if (method == "POST") return HttpMethod.Post; if (method == "PUT") return HttpMethod.Put; if (method == "HEAD") return HttpMethod.Head; if (method == "DELETE") return HttpMethod.Delete; if (method == "PATCH") return _patchMethod; return new HttpMethod(method); } internal static HttpRequestMessage BuildHttpRequestMessage(PipelineRequest request, CancellationToken cancellationToken) { if ((object)request.Uri == null) throw new InvalidOperationException("Uri must be set on message request prior to sending message."); HttpMethod method = ToHttpMethod(request.Method); Uri uri = request.Uri; HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, uri); MessageBodyAdapter messageBodyAdapter = (MessageBodyAdapter)(httpRequestMessage.Content = ((request.Content == null) ? null : new MessageBodyAdapter(request.Content, cancellationToken))); httpRequestMessage.Headers.ExpectContinue = false; ArrayBackedRequestHeaders arrayBackedRequestHeaders = request.Headers as ArrayBackedRequestHeaders; if (arrayBackedRequestHeaders == null) throw new InvalidOperationException($"""{request.Headers?.GetType()}"""); int num = 0; string name; object value; while (arrayBackedRequestHeaders.GetNextValue(num++, out name, out value)) { string text = value as string; AuthenticationHeaderValue parsedValue; if (text == null) { List<string> list = value as List<string>; if (list != null && !httpRequestMessage.Headers.TryAddWithoutValidation(name, list) && messageBodyAdapter != null && !messageBodyAdapter.Headers.TryAddWithoutValidation(name, list)) throw new InvalidOperationException("Unable to add header " + name + " to header collection."); } else if (name == "Authorization" && AuthenticationHeaderValue.TryParse(text, out parsedValue)) { httpRequestMessage.Headers.Authorization = parsedValue; } else if (!httpRequestMessage.Headers.TryAddWithoutValidation(name, text) && messageBodyAdapter != null && !messageBodyAdapter.Headers.TryAddWithoutValidation(name, text)) { throw new InvalidOperationException("Unable to add header " + name + " to header collection."); } } return httpRequestMessage; } public override string ToString() { return BuildHttpRequestMessage(this, default(CancellationToken)).ToString(); } public sealed override void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected void Dispose(bool disposing) { if (disposing && !_disposed) { BinaryContent content = _content; if (content != null) { _content = null; content.Dispose(); } _disposed = true; } } } [System.Runtime.CompilerServices.Nullable(0)] private class HttpClientTransportResponse : PipelineResponse { [System.Runtime.CompilerServices.NullableContext(0)] private class BufferedContentStream : MemoryStream { } private readonly HttpResponseMessage _httpResponse; private readonly HttpContent _httpResponseContent; [System.Runtime.CompilerServices.Nullable(2)] private Stream _contentStream; [System.Runtime.CompilerServices.Nullable(2)] private BinaryData _bufferedContent; private bool _disposed; public override int Status => (int)_httpResponse.StatusCode; public override string ReasonPhrase => _httpResponse.ReasonPhrase ?? string.Empty; protected override PipelineResponseHeaders HeadersCore => new HttpClientResponseHeaders(_httpResponse, _httpResponseContent); [System.Runtime.CompilerServices.Nullable(2)] public override Stream ContentStream { [System.Runtime.CompilerServices.NullableContext(2)] get { if (_contentStream != null) return _contentStream; return BufferContent(default(CancellationToken)).ToStream(); } [System.Runtime.CompilerServices.NullableContext(2)] set { _contentStream = value; _bufferedContent = null; } } public override BinaryData Content { get { if (_bufferedContent != null) return _bufferedContent; if (_contentStream == null || _contentStream is MemoryStream) return BufferContent(default(CancellationToken)); throw new InvalidOperationException("The response is not buffered."); } } public HttpClientTransportResponse(HttpResponseMessage httpResponse) { if (httpResponse == null) throw new ArgumentNullException("httpResponse"); _httpResponse = httpResponse; _httpResponseContent = _httpResponse.Content; _httpResponse.Content = null; } public override BinaryData BufferContent(CancellationToken cancellationToken = default(CancellationToken)) { return BufferContentSyncOrAsync(cancellationToken, false).EnsureCompleted(); } [AsyncStateMachine(typeof(<BufferContentAsync>d__18))] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public override ValueTask<BinaryData> BufferContentAsync(CancellationToken cancellationToken = default(CancellationToken)) { <BufferContentAsync>d__18 stateMachine = default(<BufferContentAsync>d__18); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<BinaryData>.Create(); stateMachine.<>4__this = this; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<BufferContentSyncOrAsync>d__19))] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private ValueTask<BinaryData> BufferContentSyncOrAsync(CancellationToken cancellationToken, bool async) { <BufferContentSyncOrAsync>d__19 stateMachine = default(<BufferContentSyncOrAsync>d__19); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<BinaryData>.Create(); stateMachine.<>4__this = this; stateMachine.cancellationToken = cancellationToken; stateMachine.async = async; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public override void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing && !_disposed) { _httpResponse?.Dispose(); if (ContentStream is MemoryStream) BufferContent(default(CancellationToken)); _contentStream?.Dispose(); _contentStream = null; _disposed = true; } } } private static readonly HttpClient _sharedDefaultClient = CreateDefaultClient(); private readonly HttpClient _httpClient; public static HttpClientPipelineTransport Shared { get; } = new HttpClientPipelineTransport(); public HttpClientPipelineTransport() : this(_sharedDefaultClient) { } public HttpClientPipelineTransport(HttpClient client) { Argument.AssertNotNull(client, "client"); _httpClient = client; } private static HttpClient CreateDefaultClient() { HttpClientHandler obj = new HttpClientHandler { AllowAutoRedirect = false }; ServicePointHelpers.SetLimits(obj); return new HttpClient(obj) { Timeout = Timeout.InfiniteTimeSpan }; } protected override PipelineMessage CreateMessageCore() { return new PipelineMessage(new HttpPipelineRequest()); } protected sealed override void ProcessCore(PipelineMessage message) { ProcessSyncOrAsync(message, true).AsTask().GetAwaiter().GetResult(); } [AsyncStateMachine(typeof(<ProcessCoreAsync>d__10))] protected sealed override ValueTask ProcessCoreAsync(PipelineMessage message) { <ProcessCoreAsync>d__10 stateMachine = default(<ProcessCoreAsync>d__10); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.message = message; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<ProcessSyncOrAsync>d__11))] private ValueTask ProcessSyncOrAsync(PipelineMessage message, bool async) { <ProcessSyncOrAsync>d__11 stateMachine = default(<ProcessSyncOrAsync>d__11); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.message = message; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } protected virtual void OnSendingRequest(PipelineMessage message, HttpRequestMessage httpRequest) { } protected virtual void OnReceivedResponse(PipelineMessage message, HttpResponseMessage httpResponse) { } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } } }