mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-08 16:36:15 +00:00
Merge pull request #6 from ridicoulous/sharedHttpClient
shared http client for multiple instances of RestClient
This commit is contained in:
commit
f444fb8478
@ -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>
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -11,21 +11,28 @@ namespace CryptoExchange.Net.Requests
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RequestFactory : IRequestFactory
|
public class RequestFactory : IRequestFactory
|
||||||
{
|
{
|
||||||
private HttpClient? httpClient;
|
private HttpClient? httpClient;
|
||||||
private bool isTracingEnabled;
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Configure(TimeSpan requestTimeout, ApiProxy? proxy)
|
|
||||||
{
|
|
||||||
HttpMessageHandler handler = new HttpClientHandler()
|
|
||||||
{
|
|
||||||
Proxy = proxy == null ? null : new WebProxy
|
|
||||||
{
|
|
||||||
Address = new Uri($"{proxy.Host}:{proxy.Port}"),
|
|
||||||
Credentials = proxy.Password == null ? null : new NetworkCredential(proxy.Login, proxy.Password)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
httpClient = new HttpClient(handler) { Timeout = requestTimeout };
|
/// <inheritdoc />
|
||||||
|
public void Configure(TimeSpan requestTimeout, ApiProxy? proxy, HttpClient? client = null)
|
||||||
|
{
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
HttpMessageHandler handler = new HttpClientHandler()
|
||||||
|
{
|
||||||
|
Proxy = proxy == null ? null : new WebProxy
|
||||||
|
{
|
||||||
|
Address = new Uri($"{proxy.Host}:{proxy.Port}"),
|
||||||
|
Credentials = proxy.Password == null ? null : new NetworkCredential(proxy.Login, proxy.Password)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
httpClient = new HttpClient(handler) { Timeout = requestTimeout };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
httpClient = client;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -24,13 +24,13 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base rest client
|
/// Base rest client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RestClient: BaseClient, IRestClient
|
public abstract class RestClient : BaseClient, IRestClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The factory for creating requests. Used for unit testing
|
/// The factory for creating requests. Used for unit testing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
|
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Where to place post parameters
|
/// Where to place post parameters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -77,13 +77,13 @@ namespace CryptoExchange.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exchangeOptions"></param>
|
/// <param name="exchangeOptions"></param>
|
||||||
/// <param name="authenticationProvider"></param>
|
/// <param name="authenticationProvider"></param>
|
||||||
protected RestClient(RestClientOptions exchangeOptions, AuthenticationProvider? authenticationProvider): base(exchangeOptions, authenticationProvider)
|
protected RestClient(RestClientOptions exchangeOptions, AuthenticationProvider? authenticationProvider) : base(exchangeOptions, authenticationProvider)
|
||||||
{
|
{
|
||||||
if (exchangeOptions == null)
|
if (exchangeOptions == null)
|
||||||
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)
|
||||||
@ -134,10 +134,10 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
reply = await ping.SendPingAsync(uri.Host).ConfigureAwait(false);
|
reply = await ping.SendPingAsync(uri.Host).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch(PingException e)
|
catch (PingException e)
|
||||||
{
|
{
|
||||||
if (e.InnerException == null)
|
if (e.InnerException == null)
|
||||||
return new CallResult<long>(0, new CantConnectError {Message = "Ping failed: " + e.Message});
|
return new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + e.Message });
|
||||||
|
|
||||||
if (e.InnerException is SocketException exception)
|
if (e.InnerException is SocketException exception)
|
||||||
return new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + exception.SocketErrorCode });
|
return new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + exception.SocketErrorCode });
|
||||||
@ -149,7 +149,7 @@ namespace CryptoExchange.Net
|
|||||||
ping.Dispose();
|
ping.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ct.IsCancellationRequested)
|
if (ct.IsCancellationRequested)
|
||||||
return new CallResult<long>(0, new CancellationRequestedError());
|
return new CallResult<long>(0, new CancellationRequestedError());
|
||||||
|
|
||||||
return reply.Status == IPStatus.Success ? new CallResult<long>(reply.RoundtripTime, null) : new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + reply.Status });
|
return reply.Status == IPStatus.Success ? new CallResult<long>(reply.RoundtripTime, null) : new CallResult<long>(0, new CantConnectError { Message = "Ping failed: " + reply.Status });
|
||||||
@ -174,7 +174,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
log.Write(LogVerbosity.Debug, "Creating request for " + uri);
|
log.Write(LogVerbosity.Debug, "Creating request for " + uri);
|
||||||
if (signed && authProvider == null)
|
if (signed && authProvider == null)
|
||||||
{
|
{
|
||||||
log.Write(LogVerbosity.Warning, $"Request {uri.AbsolutePath} failed because no ApiCredentials were provided");
|
log.Write(LogVerbosity.Warning, $"Request {uri.AbsolutePath} failed because no ApiCredentials were provided");
|
||||||
return new WebCallResult<T>(null, null, null, new NoApiCredentialsError());
|
return new WebCallResult<T>(null, null, null, new NoApiCredentialsError());
|
||||||
}
|
}
|
||||||
@ -185,19 +185,19 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (limitResult.Data > 0)
|
if (limitResult.Data > 0)
|
||||||
log.Write(LogVerbosity.Debug, $"Request {request.RequestId} {uri.AbsolutePath} was limited by {limitResult.Data}ms by {limiter.GetType().Name}");
|
log.Write(LogVerbosity.Debug, $"Request {request.RequestId} {uri.AbsolutePath} was limited by {limitResult.Data}ms by {limiter.GetType().Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
string? paramString = null;
|
string? paramString = null;
|
||||||
if (method == HttpMethod.Post)
|
if (method == HttpMethod.Post)
|
||||||
paramString = " with request body " + request.Content;
|
paramString = " with request body " + request.Content;
|
||||||
|
|
||||||
log.Write(LogVerbosity.Debug, $"Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null? "": $" via proxy {apiProxy.Host}")} with id {request.RequestId}");
|
log.Write(LogVerbosity.Debug, $"Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null ? "" : $" via proxy {apiProxy.Host}")} with id {request.RequestId}");
|
||||||
return await GetResponse<T>(request, cancellationToken).ConfigureAwait(false);
|
return await GetResponse<T>(request, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ namespace CryptoExchange.Net
|
|||||||
if (!parseResult.Success)
|
if (!parseResult.Success)
|
||||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, new ServerError(data));
|
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, new ServerError(data));
|
||||||
var error = await TryParseError(parseResult.Data);
|
var error = await TryParseError(parseResult.Data);
|
||||||
if(error != null)
|
if (error != null)
|
||||||
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
||||||
|
|
||||||
var deserializeResult = Deserialize<T>(parseResult.Data);
|
var deserializeResult = Deserialize<T>(parseResult.Data);
|
||||||
@ -253,7 +253,7 @@ namespace CryptoExchange.Net
|
|||||||
responseStream.Close();
|
responseStream.Close();
|
||||||
response.Close();
|
response.Close();
|
||||||
var parseResult = ValidateJson(data);
|
var parseResult = ValidateJson(data);
|
||||||
return new WebCallResult<T>(statusCode, headers, default, parseResult.Success ? ParseErrorResponse(parseResult.Data) :new ServerError(data));
|
return new WebCallResult<T>(statusCode, headers, default, parseResult.Success ? ParseErrorResponse(parseResult.Data) : new ServerError(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (HttpRequestException requestException)
|
catch (HttpRequestException requestException)
|
||||||
@ -263,7 +263,7 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
catch (TaskCanceledException canceledException)
|
catch (TaskCanceledException canceledException)
|
||||||
{
|
{
|
||||||
if(canceledException.CancellationToken == cancellationToken)
|
if (canceledException.CancellationToken == cancellationToken)
|
||||||
{
|
{
|
||||||
// Cancellation token cancelled
|
// Cancellation token cancelled
|
||||||
log.Write(LogVerbosity.Warning, $"Request {request.RequestId} cancel requested");
|
log.Write(LogVerbosity.Warning, $"Request {request.RequestId} cancel requested");
|
||||||
@ -305,10 +305,10 @@ namespace CryptoExchange.Net
|
|||||||
parameters = new Dictionary<string, object>();
|
parameters = new Dictionary<string, object>();
|
||||||
|
|
||||||
var uriString = uri.ToString();
|
var uriString = uri.ToString();
|
||||||
if(authProvider != null)
|
if (authProvider != null)
|
||||||
parameters = authProvider.AddAuthenticationToParameters(uriString, method, parameters, signed, postPosition, arraySerialization);
|
parameters = authProvider.AddAuthenticationToParameters(uriString, method, parameters, signed, postPosition, arraySerialization);
|
||||||
|
|
||||||
if((method == HttpMethod.Get || method == HttpMethod.Delete || postPosition == PostParameters.InUri) && parameters?.Any() == true)
|
if ((method == HttpMethod.Get || method == HttpMethod.Delete || postPosition == PostParameters.InUri) && parameters?.Any() == true)
|
||||||
uriString += "?" + parameters.CreateParamString(true, arraySerialization);
|
uriString += "?" + parameters.CreateParamString(true, arraySerialization);
|
||||||
|
|
||||||
var contentType = requestBodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
|
var contentType = requestBodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
|
||||||
@ -324,7 +324,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
if ((method == HttpMethod.Post || method == HttpMethod.Put) && postPosition != PostParameters.InUri)
|
if ((method == HttpMethod.Post || method == HttpMethod.Put) && postPosition != PostParameters.InUri)
|
||||||
{
|
{
|
||||||
if(parameters?.Any() == true)
|
if (parameters?.Any() == true)
|
||||||
WriteParamBody(request, parameters, contentType);
|
WriteParamBody(request, parameters, contentType);
|
||||||
else
|
else
|
||||||
request.SetContent(requestBodyEmptyContent, contentType);
|
request.SetContent(requestBodyEmptyContent, contentType);
|
||||||
@ -346,7 +346,7 @@ namespace CryptoExchange.Net
|
|||||||
var stringData = JsonConvert.SerializeObject(parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value));
|
var stringData = JsonConvert.SerializeObject(parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value));
|
||||||
request.SetContent(stringData, contentType);
|
request.SetContent(stringData, contentType);
|
||||||
}
|
}
|
||||||
else if(requestBodyFormat == RequestBodyFormat.FormData)
|
else if (requestBodyFormat == RequestBodyFormat.FormData)
|
||||||
{
|
{
|
||||||
var formData = HttpUtility.ParseQueryString(string.Empty);
|
var formData = HttpUtility.ParseQueryString(string.Empty);
|
||||||
foreach (var kvp in parameters.OrderBy(p => p.Key))
|
foreach (var kvp in parameters.OrderBy(p => p.Key))
|
||||||
@ -354,7 +354,7 @@ namespace CryptoExchange.Net
|
|||||||
if (kvp.Value.GetType().IsArray)
|
if (kvp.Value.GetType().IsArray)
|
||||||
{
|
{
|
||||||
var array = (Array)kvp.Value;
|
var array = (Array)kvp.Value;
|
||||||
foreach(var value in array)
|
foreach (var value in array)
|
||||||
formData.Add(kvp.Key, value.ToString());
|
formData.Add(kvp.Key, value.ToString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -363,7 +363,7 @@ namespace CryptoExchange.Net
|
|||||||
var stringData = formData.ToString();
|
var stringData = formData.ToString();
|
||||||
request.SetContent(stringData, contentType);
|
request.SetContent(stringData, contentType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parse an error response from the server. Only used when server returns a status other than Success(200)
|
/// Parse an error response from the server. Only used when server returns a status other than Success(200)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user