1
0
mirror of https://github.com/JKorf/CryptoExchange.Net.git synced 2026-08-12 17:03:10 +00:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Jan Korf 1739769f87 Updated version 2022-04-14 15:40:51 +02:00
Jan Korf 7ccf643a34 Fixed tests 2022-04-14 15:09:38 +02:00
Jan Korf edfaa650bf Moved some parameters from BaseRestClient to RestApiClient to support different setting between different sub api's 2022-04-14 15:06:52 +02:00
Jan Korf 13c81afb79 Merge pull request #135 from mohammadj22/ImproveWebSocketClientProxy
change SetProxy method in web socket client to support socks5 proxy.
2022-04-14 15:05:19 +02:00
Mohammad Reza c4f4ddcdc5 Update SetProxy 2022-04-13 17:37:48 +04:30
Mohammad Reza 4f4d2ccff3 add Schema check 2022-04-13 13:18:38 +04:30
Mohammad Reza 4db43517b7 change SetProxy method to support socks5 proxy. 2022-04-07 12:44:12 +04:30
Jkorf 41f38e040e Added missing SetApiCredentials on socket client 2022-03-24 15:47:06 +01:00
10 changed files with 81 additions and 56 deletions
@@ -144,7 +144,7 @@ namespace CryptoExchange.Net.UnitTests
}
});
client.SetParameterPosition(new HttpMethod(method), pos);
client.Api1.SetParameterPosition(new HttpMethod(method), pos);
client.SetResponse("{}", out var request);
@@ -31,11 +31,6 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
RequestFactory = new Mock<IRequestFactory>().Object;
}
public void SetParameterPosition(HttpMethod method, HttpMethodParameterPosition position)
{
ParameterPositions[method] = position;
}
public void SetResponse(string responseData, out IRequest requestObj)
{
var expectedBytes = Encoding.UTF8.GetBytes(responseData);
@@ -120,7 +115,11 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
{
public TestRestApi1Client(TestClientOptions options): base(options, options.Api1Options)
{
}
public void SetParameterPosition(HttpMethod method, HttpMethodParameterPosition position)
{
ParameterPositions[method] = position;
}
public override TimeSpan GetTimeOffset()
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Objects;
@@ -31,6 +33,37 @@ namespace CryptoExchange.Net
}
}
/// <summary>
/// Where to put the parameters for requests with different Http methods
/// </summary>
public Dictionary<HttpMethod, HttpMethodParameterPosition> ParameterPositions { get; set; } = new Dictionary<HttpMethod, HttpMethodParameterPosition>
{
{ HttpMethod.Get, HttpMethodParameterPosition.InUri },
{ HttpMethod.Post, HttpMethodParameterPosition.InBody },
{ HttpMethod.Delete, HttpMethodParameterPosition.InBody },
{ HttpMethod.Put, HttpMethodParameterPosition.InBody }
};
/// <summary>
/// Request body content type
/// </summary>
public RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json;
/// <summary>
/// Whether or not we need to manually parse an error instead of relying on the http status code
/// </summary>
public bool manualParseError = false;
/// <summary>
/// How to serialize array parameters when making requests
/// </summary>
public ArrayParametersSerialization arraySerialization = ArrayParametersSerialization.Array;
/// <summary>
/// What request body should be set when no data is send (only used in combination with postParametersPosition.InBody)
/// </summary>
public string requestBodyEmptyContent = "{}";
/// <summary>
/// The base address for this API client
/// </summary>
+14 -43
View File
@@ -26,38 +26,7 @@ namespace CryptoExchange.Net
/// The factory for creating requests. Used for unit testing
/// </summary>
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
/// <summary>
/// Where to put the parameters for requests with different Http methods
/// </summary>
protected Dictionary<HttpMethod, HttpMethodParameterPosition> ParameterPositions { get; set; } = new Dictionary<HttpMethod, HttpMethodParameterPosition>
{
{ HttpMethod.Get, HttpMethodParameterPosition.InUri },
{ HttpMethod.Post, HttpMethodParameterPosition.InBody },
{ HttpMethod.Delete, HttpMethodParameterPosition.InBody },
{ HttpMethod.Put, HttpMethodParameterPosition.InBody }
};
/// <summary>
/// Request body content type
/// </summary>
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>
/// How to serialize array parameters when making requests
/// </summary>
protected ArrayParametersSerialization arraySerialization = ArrayParametersSerialization.Array;
/// <summary>
/// What request body should be set when no data is send (only used in combination with postParametersPosition.InBody)
/// </summary>
protected string requestBodyEmptyContent = "{}";
/// <inheritdoc />
public int TotalRequestsMade => ApiClients.OfType<RestApiClient>().Sum(s => s.TotalRequestsMade);
@@ -154,8 +123,8 @@ namespace CryptoExchange.Net
}
log.Write(LogLevel.Information, $"[{requestId}] Creating request for " + uri);
var paramsPosition = parameterPosition ?? ParameterPositions[method];
var request = ConstructRequest(apiClient, uri, method, parameters, signed, paramsPosition, arraySerialization ?? this.arraySerialization, requestId, additionalHeaders);
var paramsPosition = parameterPosition ?? apiClient.ParameterPositions[method];
var request = ConstructRequest(apiClient, uri, method, parameters, signed, paramsPosition, arraySerialization ?? apiClient.arraySerialization, requestId, additionalHeaders);
string? paramString = "";
if (paramsPosition == HttpMethodParameterPosition.InBody)
@@ -167,17 +136,18 @@ namespace CryptoExchange.Net
apiClient.TotalRequestsMade++;
log.Write(LogLevel.Trace, $"[{requestId}] Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(ClientOptions.Proxy == null ? "" : $" via proxy {ClientOptions.Proxy.Host}")}");
return await GetResponseAsync<T>(request, deserializer, cancellationToken).ConfigureAwait(false);
return await GetResponseAsync<T>(apiClient, request, deserializer, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Executes the request and returns the result deserialized into the type parameter class
/// </summary>
/// <param name="apiClient">The client making the request</param>
/// <param name="request">The request object to execute</param>
/// <param name="deserializer">The JsonSerializer to use for deserialization</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns></returns>
protected virtual async Task<WebCallResult<T>> GetResponseAsync<T>(IRequest request, JsonSerializer? deserializer, CancellationToken cancellationToken)
protected virtual async Task<WebCallResult<T>> GetResponseAsync<T>(BaseApiClient apiClient, IRequest request, JsonSerializer? deserializer, CancellationToken cancellationToken)
{
try
{
@@ -191,7 +161,7 @@ namespace CryptoExchange.Net
{
// If we have to manually parse error responses (can't rely on HttpStatusCode) we'll need to read the full
// response before being able to deserialize it into the resulting type since we don't know if it an error response or data
if (manualParseError)
if (apiClient.manualParseError)
{
using var reader = new StreamReader(responseStream);
var data = await reader.ReadToEndAsync().ConfigureAwait(false);
@@ -362,11 +332,11 @@ namespace CryptoExchange.Net
if (parameterPosition == HttpMethodParameterPosition.InBody)
{
var contentType = requestBodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
var contentType = apiClient.requestBodyFormat == RequestBodyFormat.Json ? Constants.JsonContentHeader : Constants.FormContentHeader;
if (bodyParameters.Any())
WriteParamBody(request, bodyParameters, contentType);
WriteParamBody(apiClient, request, bodyParameters, contentType);
else
request.SetContent(requestBodyEmptyContent, contentType);
request.SetContent(apiClient.requestBodyEmptyContent, contentType);
}
return request;
@@ -375,18 +345,19 @@ namespace CryptoExchange.Net
/// <summary>
/// Writes the parameters of the request to the request object body
/// </summary>
/// <param name="apiClient">The client making the request</param>
/// <param name="request">The request to set the parameters on</param>
/// <param name="parameters">The parameters to set</param>
/// <param name="contentType">The content type of the data</param>
protected virtual void WriteParamBody(IRequest request, SortedDictionary<string, object> parameters, string contentType)
protected virtual void WriteParamBody(BaseApiClient apiClient, IRequest request, SortedDictionary<string, object> parameters, string contentType)
{
if (requestBodyFormat == RequestBodyFormat.Json)
if (apiClient.requestBodyFormat == RequestBodyFormat.Json)
{
// Write the parameters as json in the body
var stringData = JsonConvert.SerializeObject(parameters);
request.SetContent(stringData, contentType);
}
else if (requestBodyFormat == RequestBodyFormat.FormData)
else if (apiClient.requestBodyFormat == RequestBodyFormat.FormData)
{
// Write the parameters as form data in the body
var stringData = parameters.ToFormData();
@@ -6,6 +6,7 @@ using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Sockets;
@@ -111,6 +112,13 @@ namespace CryptoExchange.Net
ClientOptions = options;
}
/// <inheritdoc />
public void SetApiCredentials(ApiCredentials credentials)
{
foreach (var apiClient in ApiClients)
apiClient.SetApiCredentials(credentials);
}
/// <summary>
/// Set a delegate to be used for processing data received from socket connections before it is processed by handlers
/// </summary>
+4 -4
View File
@@ -6,16 +6,16 @@
<PackageId>CryptoExchange.Net</PackageId>
<Authors>JKorf</Authors>
<Description>A base package for implementing cryptocurrency API's</Description>
<PackageVersion>5.1.6</PackageVersion>
<AssemblyVersion>5.1.6</AssemblyVersion>
<FileVersion>5.1.6</FileVersion>
<PackageVersion>5.1.7</PackageVersion>
<AssemblyVersion>5.1.7</AssemblyVersion>
<FileVersion>5.1.7</FileVersion>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/JKorf/CryptoExchange.Net.git</RepositoryUrl>
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
<NeutralLanguage>en</NeutralLanguage>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageReleaseNotes>5.1.6 - Updated EnumConverter to properly handle emtpy/null and default values</PackageReleaseNotes>
<PackageReleaseNotes>5.1.7 - Moved some Rest parameters from BaseRestClient to RestApiClient to allow different implementations for sub clients</PackageReleaseNotes>
<Nullable>enable</Nullable>
<LangVersion>9.0</LangVersion>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
-2
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -491,7 +490,6 @@ namespace CryptoExchange.Net
return ub.Uri;
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Sockets;
@@ -15,6 +16,12 @@ namespace CryptoExchange.Net.Interfaces
/// </summary>
BaseSocketClientOptions ClientOptions { get; }
/// <summary>
/// Set the API credentials for this client. All Api clients in this client will use the new credentials, regardless of earlier set options.
/// </summary>
/// <param name="credentials">The credentials to set</param>
void SetApiCredentials(ApiCredentials credentials);
/// <summary>
/// Incoming kilobytes per second of data
/// </summary>
@@ -212,7 +212,13 @@ namespace CryptoExchange.Net.Sockets
/// <inheritdoc />
public virtual void SetProxy(ApiProxy proxy)
{
_socket.Options.Proxy = new WebProxy(proxy.Host, proxy.Port);
Uri.TryCreate($"{proxy.Host}:{proxy.Port}", UriKind.Absolute, out var uri);
_socket.Options.Proxy = uri?.Scheme == null
? _socket.Options.Proxy = new WebProxy(proxy.Host, proxy.Port)
: _socket.Options.Proxy = new WebProxy
{
Address = uri
};
if (proxy.Login != null)
_socket.Options.Proxy.Credentials = new NetworkCredential(proxy.Login, proxy.Password);
}
+3
View File
@@ -18,6 +18,9 @@ I develop and maintain this package on my own for free in my spare time. Donatio
Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf)
## Release notes
* Version 5.1.7 - 14 Apr 2022
* Moved some Rest parameters from BaseRestClient to RestApiClient to allow different implementations for sub clients
* Version 5.1.6 - 10 Mar 2022
* Updated EnumConverter to properly handle emtpy/null and default values