using System.IO; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using k8s.Autorest; namespace k8s { public partial class Kubernetes : AbstractKubernetes, IKubernetes { private Uri baseuri; /// /// The base URI of the service. /// public Uri BaseUri { get => baseuri; set { var baseUrl = value?.AbsoluteUri ?? throw new ArgumentNullException(nameof(BaseUri)); baseuri = new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/")); } } /// /// Subscription credentials which uniquely identify client subscription. /// public ServiceClientCredentials Credentials { get; private set; } public HttpClient HttpClient { get; protected set; } /// /// Reference to the first HTTP handler (which is the start of send HTTP /// pipeline). /// private HttpMessageHandler FirstMessageHandler { get; set; } /// /// Reference to the innermost HTTP handler (which is the end of send HTTP /// pipeline). /// #if NET5_0_OR_GREATER private SocketsHttpHandler HttpClientHandler { get; set; } #else private HttpClientHandler HttpClientHandler { get; set; } #endif /// /// Initializes client properties. /// private void Initialize() { BaseUri = new Uri("http://localhost"); } protected internal override async Task> CreateResultAsync(HttpRequestMessage httpRequest, HttpResponseMessage httpResponse, bool? watch, CancellationToken cancellationToken) { if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (httpResponse == null) { throw new ArgumentNullException(nameof(httpResponse)); } var result = new HttpOperationResponse() { Request = httpRequest, Response = httpResponse }; if (watch == true) { #if NETSTANDARD2_0 || NET48 throw new KubernetesException("watch not supported"); #else httpResponse.Content = new LineSeparatedHttpContent(httpResponse.Content, cancellationToken); #endif } try { #if NET5_0_OR_GREATER using (Stream stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false)) #else using (Stream stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false)) #endif { result.Body = KubernetesJson.Deserialize(stream); } } catch (JsonException) { httpRequest.Dispose(); httpResponse.Dispose(); throw; } return result; } protected internal override HttpRequestMessage CreateRequest(string relativeUri, HttpMethod method, IReadOnlyDictionary> customHeaders) { var httpRequest = new HttpRequestMessage(); httpRequest.Method = method; httpRequest.RequestUri = new Uri(BaseUri, relativeUri); #if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER httpRequest.Version = HttpVersion.Version20; #endif // Set Headers if (customHeaders != null) { foreach (var header in customHeaders) { httpRequest.Headers.Remove(header.Key); httpRequest.Headers.TryAddWithoutValidation(header.Key, header.Value); } } return httpRequest; } protected internal override async Task SendRequestRaw(string requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken) { if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } // Set Credentials if (Credentials != null) { cancellationToken.ThrowIfCancellationRequested(); await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); } // Send Request cancellationToken.ThrowIfCancellationRequested(); var httpResponse = await HttpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); HttpStatusCode statusCode = httpResponse.StatusCode; cancellationToken.ThrowIfCancellationRequested(); if (!httpResponse.IsSuccessStatusCode) { string responseContent = null; var ex = new HttpOperationException(string.Format("Operation returned an invalid status code '{0}'", statusCode)); if (httpResponse.Content != null) { responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); } else { responseContent = string.Empty; } ex.Request = new HttpRequestMessageWrapper(httpRequest, requestContent); ex.Response = new HttpResponseMessageWrapper(httpResponse, responseContent); httpRequest.Dispose(); if (httpResponse != null) { httpResponse.Dispose(); } throw ex; } return httpResponse; } /// /// Indicates whether the ServiceClient has been disposed. /// private bool _disposed; /// /// Dispose the ServiceClient. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose the HttpClient and Handlers. /// /// True to release both managed and unmanaged resources; false to releases only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposed) { _disposed = true; // Dispose the client HttpClient?.Dispose(); HttpClient = null; FirstMessageHandler = null; HttpClientHandler = null; } } } }