mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-09 00:46:19 +00:00
Added requestBodyEmptyContent setting for rest client, Added TryParseError for rest implementations to check for error with success status code
This commit is contained in:
parent
6e4df34aea
commit
b95215866b
@ -6,12 +6,12 @@
|
|||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>A base package for implementing cryptocurrency exchange API's</Description>
|
<Description>A base package for implementing cryptocurrency exchange API's</Description>
|
||||||
<PackageVersion>3.0.7</PackageVersion>
|
<PackageVersion>3.0.8</PackageVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
||||||
<NeutralLanguage>en</NeutralLanguage>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<PackageReleaseNotes>3.0.7 - Added error debug output, Fix for unsubscribe causing possible deadlock</PackageReleaseNotes>
|
<PackageReleaseNotes>3.0.8 - Added empty body content setting, added TryParseError virtual method</PackageReleaseNotes>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
@ -2112,6 +2112,11 @@
|
|||||||
Request body content type
|
Request body content type
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="F:CryptoExchange.Net.RestClient.manualParseError">
|
||||||
|
<summary>
|
||||||
|
Whether or not we need to manually parse an error instead of relying on the http status code
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="F:CryptoExchange.Net.RestClient.arraySerialization">
|
<member name="F:CryptoExchange.Net.RestClient.arraySerialization">
|
||||||
<summary>
|
<summary>
|
||||||
How to serialize array parameters
|
How to serialize array parameters
|
||||||
@ -2188,6 +2193,14 @@
|
|||||||
<param name="cancellationToken">Cancellation token</param>
|
<param name="cancellationToken">Cancellation token</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:CryptoExchange.Net.RestClient.TryParseError(Newtonsoft.Json.Linq.JToken)">
|
||||||
|
<summary>
|
||||||
|
Can be used to parse an error even though response status indicates success. Some apis always return 200 OK, even though there is an error.
|
||||||
|
This can be used together with ManualParseError to check if it is an error before deserializing to an object
|
||||||
|
</summary>
|
||||||
|
<param name="data">Received data</param>
|
||||||
|
<returns>Null if not an error, Error otherwise</returns>
|
||||||
|
</member>
|
||||||
<member name="M:CryptoExchange.Net.RestClient.ConstructRequest(System.Uri,System.Net.Http.HttpMethod,System.Collections.Generic.Dictionary{System.String,System.Object},System.Boolean)">
|
<member name="M:CryptoExchange.Net.RestClient.ConstructRequest(System.Uri,System.Net.Http.HttpMethod,System.Collections.Generic.Dictionary{System.String,System.Object},System.Boolean)">
|
||||||
<summary>
|
<summary>
|
||||||
Creates a request object
|
Creates a request object
|
||||||
@ -2926,5 +2939,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>
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
@ -39,11 +40,21 @@ namespace CryptoExchange.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json;
|
protected RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not we need to manually parse an error instead of relying on the http status code
|
||||||
|
/// </summary>
|
||||||
|
protected bool manualParseError = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How to serialize array parameters
|
/// How to serialize array parameters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ArrayParametersSerialization arraySerialization = ArrayParametersSerialization.Array;
|
protected ArrayParametersSerialization arraySerialization = ArrayParametersSerialization.Array;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// What request body should be when no data is send
|
||||||
|
/// </summary>
|
||||||
|
protected string requestBodyEmptyContent = "{}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout for requests
|
/// Timeout for requests
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -205,11 +216,32 @@ namespace CryptoExchange.Net
|
|||||||
var responseStream = await response.GetResponseStream().ConfigureAwait(false);
|
var responseStream = await response.GetResponseStream().ConfigureAwait(false);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var desResult = await Deserialize<T>(responseStream).ConfigureAwait(false);
|
if (manualParseError)
|
||||||
responseStream.Close();
|
{
|
||||||
response.Close();
|
using var reader = new StreamReader(responseStream);
|
||||||
|
var data = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||||
|
responseStream.Close();
|
||||||
|
response.Close();
|
||||||
|
log.Write(LogVerbosity.Debug, $"Data received: {data}");
|
||||||
|
|
||||||
return new WebCallResult<T>(statusCode, headers, desResult.Data, desResult.Error);
|
var parseResult = ValidateJson(data);
|
||||||
|
if (!parseResult.Success)
|
||||||
|
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, new ServerError(data));
|
||||||
|
var error = await TryParseError(parseResult.Data);
|
||||||
|
if(error != null)
|
||||||
|
return WebCallResult<T>.CreateErrorResult(response.StatusCode, response.ResponseHeaders, error);
|
||||||
|
|
||||||
|
var deserializeResult = Deserialize<T>(parseResult.Data);
|
||||||
|
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, deserializeResult.Data, deserializeResult.Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var desResult = await Deserialize<T>(responseStream).ConfigureAwait(false);
|
||||||
|
responseStream.Close();
|
||||||
|
response.Close();
|
||||||
|
|
||||||
|
return new WebCallResult<T>(statusCode, headers, desResult.Data, desResult.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -244,6 +276,17 @@ namespace CryptoExchange.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can be used to parse an error even though response status indicates success. Some apis always return 200 OK, even though there is an error.
|
||||||
|
/// This can be used together with ManualParseError to check if it is an error before deserializing to an object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Received data</param>
|
||||||
|
/// <returns>Null if not an error, Error otherwise</returns>
|
||||||
|
protected virtual Task<ServerError?> TryParseError(JToken data)
|
||||||
|
{
|
||||||
|
return Task.FromResult<ServerError?>(null);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a request object
|
/// Creates a request object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -280,7 +323,7 @@ namespace CryptoExchange.Net
|
|||||||
if(parameters?.Any() == true)
|
if(parameters?.Any() == true)
|
||||||
WriteParamBody(request, parameters, contentType);
|
WriteParamBody(request, parameters, contentType);
|
||||||
else
|
else
|
||||||
request.SetContent("{}", contentType);
|
request.SetContent(requestBodyEmptyContent, contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
|
@ -194,6 +194,10 @@ The order book will automatically reconnect when the connection is lost and resy
|
|||||||
To stop synchronizing an order book use the `Stop` method.
|
To stop synchronizing an order book use the `Stop` method.
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
* Version 3.0.8 - 02 Jun 2020
|
||||||
|
* Added requestBodyEmptyContent setting for rest client
|
||||||
|
* Added TryParseError for rest implementations to check for error with success status code
|
||||||
|
|
||||||
* Version 3.0.7 - 20 May 2020
|
* Version 3.0.7 - 20 May 2020
|
||||||
* Added error debug output
|
* Added error debug output
|
||||||
* Fix for unsubscribe causing possible deadlock
|
* Fix for unsubscribe causing possible deadlock
|
||||||
|
Loading…
x
Reference in New Issue
Block a user