src/AlibabaCloud.OSS.V2/Transport/HttpTransport.cs (92 lines of code) (raw):
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
#if NETCOREAPP
using System.Net.Security;
#endif
namespace AlibabaCloud.OSS.V2.Transport
{
/// <summary>
/// An implementation that uses <see cref="HttpClient"/> as the transport.
/// </summary>
public class HttpTransport : IDisposable
{
/// <summary>
/// A shared instance of <see cref="HttpTransport"/> with default parameters.
/// </summary>
public static readonly HttpTransport Shared = new HttpTransport();
// The transport's private HttpClient is internal because it is used by tests.
internal HttpClient Client { get; }
internal bool _disposeClient = true;
/// <summary>
/// Creates a new <see cref="HttpTransport"/> instance using default configuration.
/// </summary>
public HttpTransport() : this(CreateDefaultClient()) { }
/// <summary>
/// Creates a new instance of <see cref="HttpTransport"/> using the provided client instance.
/// </summary>
/// <param name="messageHandler">The instance of <see cref="HttpMessageHandler"/> to use.</param>
public HttpTransport(HttpMessageHandler messageHandler)
{
Client = new HttpClient(messageHandler) ?? throw new ArgumentNullException(nameof(messageHandler));
}
/// <summary>
/// Creates a new instance of <see cref="HttpTransport"/> using the provided client instance.
/// </summary>
/// <param name="client">The instance of <see cref="HttpClient"/> to use.</param>
/// <param name="disposeClient">true if the inner client should be disposed of by Dispose(), false if you intend
/// to reuse the inner client.</param>
public HttpTransport(HttpClient client, bool disposeClient = true)
{
Client = client ?? throw new ArgumentNullException(nameof(client));
_disposeClient = disposeClient;
}
/// <summary>
/// Send an HTTP request as an asynchronous operation.
/// <param name="request">The HTTP request message to send.</param>
/// <param name="completionOption">When the operation should complete (as soon as a response is available or after
/// reading the whole response content)</param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
/// </summary>
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
return Client.SendAsync(request, completionOption, cancellationToken);
}
/// <summary>
/// Disposes the underlying <see cref="HttpClient"/>.
/// </summary>
public void Dispose()
{
if (this != Shared)
{
if (_disposeClient)
{
Client.Dispose();
}
}
GC.SuppressFinalize(this);
}
static HttpClient CreateDefaultClient(HttpTransportOptions? options = null)
{
return CreateCustomClient();
}
public static HttpClient CreateCustomClient(HttpTransportOptions? options = null)
{
var httpMessageHandler = CreateDefaultHandler(options);
return new HttpClient(httpMessageHandler)
{
// Timeouts are handled by the pipeline
Timeout = Timeout.InfiniteTimeSpan,
};
}
#if NETCOREAPP
private static HttpMessageHandler CreateDefaultHandler(HttpTransportOptions? options = null)
{
var opt = options ?? new HttpTransportOptions();
var handler = new SocketsHttpHandler {
ConnectTimeout = opt.ConnectTimeout.GetValueOrDefault(HttpTransportOptions.DEFAULT_CONNECT_TIMEOUT),
Expect100ContinueTimeout = opt.ExpectContinueTimeout.GetValueOrDefault(HttpTransportOptions.DEFAULT_EXPECT_CONTINUE_TIMEOUT),
PooledConnectionIdleTimeout = opt.IdleConnectionTimeout.GetValueOrDefault(HttpTransportOptions.DEFAULT_IDLE_CONNECTION_TIMEOUT),
KeepAlivePingTimeout = opt.KeepAliveTimeout.GetValueOrDefault(HttpTransportOptions.DEFAULT_KEEP_ALIVE_TIMEOUT),
MaxConnectionsPerServer = opt.MaxConnections.GetValueOrDefault(HttpTransportOptions.DEFAULT_MAX_CONNECTIONS),
AllowAutoRedirect = opt.EnabledRedirect.GetValueOrDefault(false),
Proxy = opt.HttpProxy
};
if (opt.InsecureSkipVerify.GetValueOrDefault(false))
{
handler.SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = delegate { return true; },
};
}
return handler;
}
#else
private static HttpMessageHandler CreateDefaultHandler(HttpTransportOptions? options = null)
{
var opt = options ?? new HttpTransportOptions();
var handler = new HttpClientHandler
{
MaxConnectionsPerServer = opt.MaxConnections.GetValueOrDefault(HttpTransportOptions.DEFAULT_MAX_CONNECTIONS),
AllowAutoRedirect = opt.EnabledRedirect.GetValueOrDefault(false),
Proxy = opt.HttpProxy
};
if (opt.InsecureSkipVerify.GetValueOrDefault(false))
{
handler.ServerCertificateCustomValidationCallback = delegate { return true; };
}
return handler;
}
#endif
}
}