1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-09 00:46:19 +00:00

Merge pull request #6 from ridicoulous/sharedHttpClient

shared http client for multiple instances of RestClient
This commit is contained in:
Artem Kurianov 2020-08-18 12:41:32 +03:00 committed by GitHub
commit f444fb8478
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 222 additions and 47 deletions

View File

@ -633,13 +633,13 @@
<param name="uri"></param> <param name="uri"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:CryptoExchange.Net.Interfaces.IRequestFactory.Configure(System.TimeSpan,CryptoExchange.Net.Objects.ApiProxy,System.Boolean)"> <member name="M:CryptoExchange.Net.Interfaces.IRequestFactory.Configure(System.TimeSpan,CryptoExchange.Net.Objects.ApiProxy,System.Net.Http.HttpClient)">
<summary> <summary>
Configure the requests created by this factory Configure the requests created by this factory
</summary> </summary>
<param name="requestTimeout">Request timeout to use</param> <param name="requestTimeout">Request timeout to use</param>
<param name="proxy">Proxy settings to use</param> <param name="proxy">Proxy settings to use</param>
<param name="isTracingEnabled">Should generate unique id for requests</param> <param name="httpClient">Optional shared http client instance</param>
</member> </member>
<member name="T:CryptoExchange.Net.Interfaces.IResponse"> <member name="T:CryptoExchange.Net.Interfaces.IResponse">
<summary> <summary>
@ -1622,12 +1622,24 @@
The time the server has to respond to a request before timing out The time the server has to respond to a request before timing out
</summary> </summary>
</member> </member>
<member name="F:CryptoExchange.Net.Objects.RestClientOptions.HttpClient">
<summary>
http client
</summary>
</member>
<member name="M:CryptoExchange.Net.Objects.RestClientOptions.#ctor(System.String)"> <member name="M:CryptoExchange.Net.Objects.RestClientOptions.#ctor(System.String)">
<summary> <summary>
ctor ctor
</summary> </summary>
<param name="baseAddress"></param> <param name="baseAddress"></param>
</member> </member>
<member name="M:CryptoExchange.Net.Objects.RestClientOptions.#ctor(System.Net.Http.HttpClient,System.String)">
<summary>
ctor
</summary>
<param name="baseAddress"></param>
<param name="httpClient">Shared http client</param>
</member>
<member name="M:CryptoExchange.Net.Objects.RestClientOptions.Copy``1"> <member name="M:CryptoExchange.Net.Objects.RestClientOptions.Copy``1">
<summary> <summary>
Create a copy of the options Create a copy of the options
@ -2030,13 +2042,12 @@
Request object Request object
</summary> </summary>
</member> </member>
<member name="M:CryptoExchange.Net.Requests.Request.#ctor(System.Net.Http.HttpRequestMessage,System.Net.Http.HttpClient,System.Boolean)"> <member name="M:CryptoExchange.Net.Requests.Request.#ctor(System.Net.Http.HttpRequestMessage,System.Net.Http.HttpClient)">
<summary> <summary>
Create request object for web request Create request object for web request
</summary> </summary>
<param name="request"></param> <param name="request"></param>
<param name="client"></param> <param name="client"></param>
<param name="isTracingEnabled">if true, should assign unique id for request</param>
</member> </member>
<member name="P:CryptoExchange.Net.Requests.Request.Content"> <member name="P:CryptoExchange.Net.Requests.Request.Content">
<inheritdoc /> <inheritdoc />
@ -2070,7 +2081,7 @@
WebRequest factory WebRequest factory
</summary> </summary>
</member> </member>
<member name="M:CryptoExchange.Net.Requests.RequestFactory.Configure(System.TimeSpan,CryptoExchange.Net.Objects.ApiProxy,System.Boolean)"> <member name="M:CryptoExchange.Net.Requests.RequestFactory.Configure(System.TimeSpan,CryptoExchange.Net.Objects.ApiProxy,System.Net.Http.HttpClient)">
<inheritdoc /> <inheritdoc />
</member> </member>
<member name="M:CryptoExchange.Net.Requests.RequestFactory.Create(System.Net.Http.HttpMethod,System.String)"> <member name="M:CryptoExchange.Net.Requests.RequestFactory.Create(System.Net.Http.HttpMethod,System.String)">
@ -2958,5 +2969,148 @@
<member name="M:CryptoExchange.Net.Sockets.WebsocketFactory.CreateWebsocket(CryptoExchange.Net.Logging.Log,System.String,System.Collections.Generic.IDictionary{System.String,System.String},System.Collections.Generic.IDictionary{System.String,System.String})"> <member name="M:CryptoExchange.Net.Sockets.WebsocketFactory.CreateWebsocket(CryptoExchange.Net.Logging.Log,System.String,System.Collections.Generic.IDictionary{System.String,System.String},System.Collections.Generic.IDictionary{System.String,System.String})">
<inheritdoc /> <inheritdoc />
</member> </member>
<member name="T:System.Diagnostics.CodeAnalysis.AllowNullAttribute">
<summary>
Specifies that <see langword="null"/> is allowed as an input even if the
corresponding type disallows it.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.AllowNullAttribute.#ctor">
<summary>
Initializes a new instance of the <see cref="T:System.Diagnostics.CodeAnalysis.AllowNullAttribute"/> class.
</summary>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.DisallowNullAttribute">
<summary>
Specifies that <see langword="null"/> is disallowed as an input even if the
corresponding type allows it.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.DisallowNullAttribute.#ctor">
<summary>
Initializes a new instance of the <see cref="T:System.Diagnostics.CodeAnalysis.DisallowNullAttribute"/> class.
</summary>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute">
<summary>
Specifies that a method that will never return under any circumstance.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute.#ctor">
<summary>
Initializes a new instance of the <see cref="T:System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute"/> class.
</summary>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute">
<summary>
Specifies that the method will not return if the associated <see cref="T:System.Boolean"/>
parameter is passed the specified value.
</summary>
</member>
<member name="P:System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute.ParameterValue">
<summary>
Gets the condition parameter value.
Code after the method is considered unreachable by diagnostics if the argument
to the associated parameter matches this value.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute.#ctor(System.Boolean)">
<summary>
Initializes a new instance of the <see cref="T:System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute"/>
class with the specified parameter value.
</summary>
<param name="parameterValue">
The condition parameter value.
Code after the method is considered unreachable by diagnostics if the argument
to the associated parameter matches this value.
</param>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.MaybeNullAttribute">
<summary>
Specifies that an output may be <see langword="null"/> even if the
corresponding type disallows it.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.MaybeNullAttribute.#ctor">
<summary>
Initializes a new instance of the <see cref="T:System.Diagnostics.CodeAnalysis.MaybeNullAttribute"/> class.
</summary>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute">
<summary>
Specifies that when a method returns <see cref="P:System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute.ReturnValue"/>,
the parameter may be <see langword="null"/> even if the corresponding type disallows it.
</summary>
</member>
<member name="P:System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute.ReturnValue">
<summary>
Gets the return value condition.
If the method returns this value, the associated parameter may be <see langword="null"/>.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute.#ctor(System.Boolean)">
<summary>
Initializes the attribute with the specified return value condition.
</summary>
<param name="returnValue">
The return value condition.
If the method returns this value, the associated parameter may be <see langword="null"/>.
</param>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.NotNullAttribute">
<summary>
Specifies that an output is not <see langword="null"/> even if the
corresponding type allows it.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.NotNullAttribute.#ctor">
<summary>
Initializes a new instance of the <see cref="T:System.Diagnostics.CodeAnalysis.NotNullAttribute"/> class.
</summary>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute">
<summary>
Specifies that the output will be non-<see langword="null"/> if the
named parameter is non-<see langword="null"/>.
</summary>
</member>
<member name="P:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute.ParameterName">
<summary>
Gets the associated parameter name.
The output will be non-<see langword="null"/> if the argument to the
parameter specified is non-<see langword="null"/>.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute.#ctor(System.String)">
<summary>
Initializes the attribute with the associated parameter name.
</summary>
<param name="parameterName">
The associated parameter name.
The output will be non-<see langword="null"/> if the argument to the
parameter specified is non-<see langword="null"/>.
</param>
</member>
<member name="T:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute">
<summary>
Specifies that when a method returns <see cref="P:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.ReturnValue"/>,
the parameter will not be <see langword="null"/> even if the corresponding type allows it.
</summary>
</member>
<member name="P:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.ReturnValue">
<summary>
Gets the return value condition.
If the method returns this value, the associated parameter will not be <see langword="null"/>.
</summary>
</member>
<member name="M:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.#ctor(System.Boolean)">
<summary>
Initializes the attribute with the specified return value condition.
</summary>
<param name="returnValue">
The return value condition.
If the method returns this value, the associated parameter will not be <see langword="null"/>.
</param>
</member>
</members> </members>
</doc> </doc>

View File

@ -22,6 +22,7 @@ namespace CryptoExchange.Net.Interfaces
/// </summary> /// </summary>
/// <param name="requestTimeout">Request timeout to use</param> /// <param name="requestTimeout">Request timeout to use</param>
/// <param name="proxy">Proxy settings to use</param> /// <param name="proxy">Proxy settings to use</param>
void Configure(TimeSpan requestTimeout, ApiProxy? proxy); /// <param name="httpClient">Optional shared http client instance</param>
void Configure(TimeSpan requestTimeout, ApiProxy? proxy, HttpClient? httpClient=null);
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Http;
using CryptoExchange.Net.Authentication; using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Interfaces; using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Logging; using CryptoExchange.Net.Logging;
@ -126,7 +127,10 @@ namespace CryptoExchange.Net.Objects
/// The time the server has to respond to a request before timing out /// The time the server has to respond to a request before timing out
/// </summary> /// </summary>
public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30); public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30);
/// <summary>
/// http client
/// </summary>
public HttpClient? HttpClient;
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
@ -134,7 +138,15 @@ namespace CryptoExchange.Net.Objects
public RestClientOptions(string baseAddress): base(baseAddress) public RestClientOptions(string baseAddress): base(baseAddress)
{ {
} }
/// <summary>
/// ctor
/// </summary>
/// <param name="baseAddress"></param>
/// <param name="httpClient">Shared http client</param>
public RestClientOptions(HttpClient httpClient, string baseAddress) : base(baseAddress)
{
HttpClient = httpClient;
}
/// <summary> /// <summary>
/// Create a copy of the options /// Create a copy of the options
/// </summary> /// </summary>
@ -150,7 +162,8 @@ namespace CryptoExchange.Net.Objects
LogWriters = LogWriters, LogWriters = LogWriters,
RateLimiters = RateLimiters, RateLimiters = RateLimiters,
RateLimitingBehaviour = RateLimitingBehaviour, RateLimitingBehaviour = RateLimitingBehaviour,
RequestTimeout = RequestTimeout RequestTimeout = RequestTimeout,
HttpClient = HttpClient
}; };
if (ApiCredentials != null) if (ApiCredentials != null)

View File

@ -12,9 +12,11 @@ namespace CryptoExchange.Net.Requests
public class RequestFactory : IRequestFactory public class RequestFactory : IRequestFactory
{ {
private HttpClient? httpClient; private HttpClient? httpClient;
private bool isTracingEnabled;
/// <inheritdoc /> /// <inheritdoc />
public void Configure(TimeSpan requestTimeout, ApiProxy? proxy) public void Configure(TimeSpan requestTimeout, ApiProxy? proxy, HttpClient? client = null)
{
if (client == null)
{ {
HttpMessageHandler handler = new HttpClientHandler() HttpMessageHandler handler = new HttpClientHandler()
{ {
@ -27,6 +29,11 @@ namespace CryptoExchange.Net.Requests
httpClient = new HttpClient(handler) { Timeout = requestTimeout }; httpClient = new HttpClient(handler) { Timeout = requestTimeout };
} }
else
{
httpClient = client;
}
}
/// <inheritdoc /> /// <inheritdoc />
public IRequest Create(HttpMethod method, string uri) public IRequest Create(HttpMethod method, string uri)

View File

@ -83,7 +83,7 @@ namespace CryptoExchange.Net
throw new ArgumentNullException(nameof(exchangeOptions)); throw new ArgumentNullException(nameof(exchangeOptions));
RequestTimeout = exchangeOptions.RequestTimeout; RequestTimeout = exchangeOptions.RequestTimeout;
RequestFactory.Configure(exchangeOptions.RequestTimeout, exchangeOptions.Proxy); RequestFactory.Configure(exchangeOptions.RequestTimeout, exchangeOptions.Proxy, exchangeOptions.HttpClient);
RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour; RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour;
var rateLimiters = new List<IRateLimiter>(); var rateLimiters = new List<IRateLimiter>();
foreach (var rateLimiter in exchangeOptions.RateLimiters) foreach (var rateLimiter in exchangeOptions.RateLimiters)
@ -185,7 +185,7 @@ namespace CryptoExchange.Net
var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour); var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour);
if (!limitResult.Success) if (!limitResult.Success)
{ {
log.Write(LogVerbosity.Debug, $"Request {uri.AbsolutePath} failed because of rate limit"); log.Write(LogVerbosity.Debug, $"Request {request.RequestId} {uri.AbsolutePath} failed because of rate limit");
return new WebCallResult<T>(null, null, null, limitResult.Error); return new WebCallResult<T>(null, null, null, limitResult.Error);
} }