1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2026-04-07 02:01:12 +00:00

Added Http options to Rest client options

This commit is contained in:
Jkorf 2026-02-24 09:58:48 +01:00
parent b29cdc41f3
commit bea2b2bd7b
3 changed files with 53 additions and 15 deletions

View File

@ -1,4 +1,5 @@
using CryptoExchange.Net.Objects; using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Options;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -105,31 +106,36 @@ namespace CryptoExchange.Net
/// <summary> /// <summary>
/// Create a new HttpMessageHandler instance /// Create a new HttpMessageHandler instance
/// </summary> /// </summary>
public static HttpMessageHandler CreateHttpClientMessageHandler(ApiProxy? proxy, TimeSpan? keepAliveInterval) public static HttpMessageHandler CreateHttpClientMessageHandler(RestExchangeOptions options)
{ {
#if NET5_0_OR_GREATER #if NET5_0_OR_GREATER
var socketHandler = new SocketsHttpHandler(); var socketHandler = new SocketsHttpHandler();
try try
{ {
if (keepAliveInterval != null && keepAliveInterval != TimeSpan.Zero) if (options.HttpKeepAliveInterval != null && options.HttpKeepAliveInterval != TimeSpan.Zero)
{ {
socketHandler.KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always; socketHandler.KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always;
socketHandler.KeepAlivePingDelay = keepAliveInterval.Value; socketHandler.KeepAlivePingDelay = options.HttpKeepAliveInterval.Value;
socketHandler.KeepAlivePingTimeout = TimeSpan.FromSeconds(10); socketHandler.KeepAlivePingTimeout = TimeSpan.FromSeconds(10);
} }
socketHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; socketHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
socketHandler.DefaultProxyCredentials = CredentialCache.DefaultCredentials; socketHandler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
socketHandler.EnableMultipleHttp2Connections = options.HttpEnableMultipleHttp2Connections;
socketHandler.PooledConnectionLifetime = options.HttpPooledConnectionLifetime;
socketHandler.PooledConnectionIdleTimeout = options.HttpPooledConnectionIdleTimeout;
socketHandler.MaxConnectionsPerServer = options.HttpMaxConnectionsPerServer;
} }
catch (PlatformNotSupportedException) { } catch (PlatformNotSupportedException) { }
catch (NotImplementedException) { } // Mono runtime throws NotImplementedException catch (NotImplementedException) { } // Mono runtime throws NotImplementedException
if (proxy != null) if (options.Proxy != null)
{ {
socketHandler.Proxy = new WebProxy socketHandler.Proxy = new WebProxy
{ {
Address = new Uri($"{proxy.Host}:{proxy.Port}"), Address = new Uri($"{options.Proxy.Host}:{options.Proxy.Port}"),
Credentials = proxy.Password == null ? null : new NetworkCredential(proxy.Login, proxy.Password) Credentials = options.Proxy.Password == null ? null : new NetworkCredential(options.Proxy.Login, options.Proxy.Password)
}; };
} }
return socketHandler; return socketHandler;
@ -143,12 +149,12 @@ namespace CryptoExchange.Net
catch (PlatformNotSupportedException) { } catch (PlatformNotSupportedException) { }
catch (NotImplementedException) { } // Mono runtime throws NotImplementedException catch (NotImplementedException) { } // Mono runtime throws NotImplementedException
if (proxy != null) if (options.Proxy != null)
{ {
httpHandler.Proxy = new WebProxy httpHandler.Proxy = new WebProxy
{ {
Address = new Uri($"{proxy.Host}:{proxy.Port}"), Address = new Uri($"{options.Proxy.Host}:{options.Proxy.Port}"),
Credentials = proxy.Password == null ? null : new NetworkCredential(proxy.Login, proxy.Password) Credentials = options.Proxy.Password == null ? null : new NetworkCredential(options.Proxy.Login, options.Proxy.Password)
}; };
} }
return httpHandler; return httpHandler;

View File

@ -32,10 +32,29 @@ namespace CryptoExchange.Net.Objects.Options
#else #else
= new Version(1, 1); = new Version(1, 1);
#endif #endif
/// <summary> /// <summary>
/// Http client keep alive interval for keeping connections open /// Http client keep alive interval for keeping connections open. Only applied when using dotnet8.0 or higher and dependency injection
/// </summary> /// </summary>
public TimeSpan? HttpKeepAliveInterval { get; set; } = TimeSpan.FromSeconds(15); public TimeSpan? HttpKeepAliveInterval { get; set; } = TimeSpan.FromSeconds(15);
#if NET5_0_OR_GREATER
/// <summary>
/// Enable multiple simultaneous HTTP 2 connections. Only applied when using dependency injection
/// </summary>
public bool HttpEnableMultipleHttp2Connections { get; set; } = false;
/// <summary>
/// Lifetime of pooled HTTP connections; the time before a connection is recreated. Only applied when using dependency injection
/// </summary>
public TimeSpan HttpPooledConnectionLifetime { get; set; } = TimeSpan.FromMinutes(15);
/// <summary>
/// Idle timeout of pooled HTTP connections; the time before an open connection is closed when there are no requests. Only applied when using dependency injection
/// </summary>
public TimeSpan HttpPooledConnectionIdleTimeout { get; set; } = TimeSpan.FromMinutes(2);
/// <summary>
/// Max number of connections per server. Only applied when using dependency injection
/// </summary>
public int HttpMaxConnectionsPerServer { get; set; } = int.MaxValue;
#endif
/// <summary> /// <summary>
/// Set the values of this options on the target options /// Set the values of this options on the target options
@ -54,6 +73,12 @@ namespace CryptoExchange.Net.Objects.Options
item.CachingMaxAge = CachingMaxAge; item.CachingMaxAge = CachingMaxAge;
item.HttpVersion = HttpVersion; item.HttpVersion = HttpVersion;
item.HttpKeepAliveInterval = HttpKeepAliveInterval; item.HttpKeepAliveInterval = HttpKeepAliveInterval;
#if NET5_0_OR_GREATER
item.HttpMaxConnectionsPerServer = HttpMaxConnectionsPerServer;
item.HttpPooledConnectionLifetime = HttpPooledConnectionLifetime;
item.HttpPooledConnectionIdleTimeout = HttpPooledConnectionIdleTimeout;
item.HttpEnableMultipleHttp2Connections = HttpEnableMultipleHttp2Connections;
#endif
return item; return item;
} }
} }

View File

@ -12,14 +12,16 @@ namespace CryptoExchange.Net.Requests
public class RequestFactory : IRequestFactory public class RequestFactory : IRequestFactory
{ {
private HttpClient? _httpClient; private HttpClient? _httpClient;
private RestExchangeOptions? _options;
/// <inheritdoc /> /// <inheritdoc />
public void Configure(RestExchangeOptions options, HttpClient? client = null) public void Configure(RestExchangeOptions options, HttpClient? client = null)
{ {
if (client == null) if (client == null)
client = CreateClient(options.Proxy, options.RequestTimeout, options.HttpKeepAliveInterval); client = CreateClient(options);
_httpClient = client; _httpClient = client;
_options = options;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -39,15 +41,20 @@ namespace CryptoExchange.Net.Requests
/// <inheritdoc /> /// <inheritdoc />
public void UpdateSettings(ApiProxy? proxy, TimeSpan requestTimeout, TimeSpan? httpKeepAliveInterval) public void UpdateSettings(ApiProxy? proxy, TimeSpan requestTimeout, TimeSpan? httpKeepAliveInterval)
{ {
_httpClient = CreateClient(proxy, requestTimeout, httpKeepAliveInterval); var newOptions = new RestExchangeOptions();
_options!.Set(newOptions);
newOptions.Proxy = proxy;
newOptions.RequestTimeout = requestTimeout;
newOptions.HttpKeepAliveInterval = httpKeepAliveInterval;
_httpClient = CreateClient(newOptions);
} }
private static HttpClient CreateClient(ApiProxy? proxy, TimeSpan requestTimeout, TimeSpan? httpKeepAliveInterval) private static HttpClient CreateClient(RestExchangeOptions options)
{ {
var handler = LibraryHelpers.CreateHttpClientMessageHandler(proxy, httpKeepAliveInterval); var handler = LibraryHelpers.CreateHttpClientMessageHandler(options);
var client = new HttpClient(handler) var client = new HttpClient(handler)
{ {
Timeout = requestTimeout Timeout = options.RequestTimeout
}; };
return client; return client;
} }