diff --git a/CryptoExchange.Net/Clients/BaseApiClient.cs b/CryptoExchange.Net/Clients/BaseApiClient.cs index 91f039b..9bde40c 100644 --- a/CryptoExchange.Net/Clients/BaseApiClient.cs +++ b/CryptoExchange.Net/Clients/BaseApiClient.cs @@ -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 } } + /// + /// Where to put the parameters for requests with different Http methods + /// + public Dictionary ParameterPositions { get; set; } = new Dictionary + { + { HttpMethod.Get, HttpMethodParameterPosition.InUri }, + { HttpMethod.Post, HttpMethodParameterPosition.InBody }, + { HttpMethod.Delete, HttpMethodParameterPosition.InBody }, + { HttpMethod.Put, HttpMethodParameterPosition.InBody } + }; + + /// + /// Request body content type + /// + public RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json; + + /// + /// Whether or not we need to manually parse an error instead of relying on the http status code + /// + public bool manualParseError = false; + + /// + /// How to serialize array parameters when making requests + /// + public ArrayParametersSerialization arraySerialization = ArrayParametersSerialization.Array; + + /// + /// What request body should be set when no data is send (only used in combination with postParametersPosition.InBody) + /// + public string requestBodyEmptyContent = "{}"; + /// /// The base address for this API client /// diff --git a/CryptoExchange.Net/Clients/BaseRestClient.cs b/CryptoExchange.Net/Clients/BaseRestClient.cs index 542050f..c5d9586 100644 --- a/CryptoExchange.Net/Clients/BaseRestClient.cs +++ b/CryptoExchange.Net/Clients/BaseRestClient.cs @@ -26,38 +26,7 @@ namespace CryptoExchange.Net /// The factory for creating requests. Used for unit testing /// public IRequestFactory RequestFactory { get; set; } = new RequestFactory(); - - /// - /// Where to put the parameters for requests with different Http methods - /// - protected Dictionary ParameterPositions { get; set; } = new Dictionary - { - { HttpMethod.Get, HttpMethodParameterPosition.InUri }, - { HttpMethod.Post, HttpMethodParameterPosition.InBody }, - { HttpMethod.Delete, HttpMethodParameterPosition.InBody }, - { HttpMethod.Put, HttpMethodParameterPosition.InBody } - }; - - /// - /// Request body content type - /// - protected RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json; - - /// - /// Whether or not we need to manually parse an error instead of relying on the http status code - /// - protected bool manualParseError = false; - - /// - /// How to serialize array parameters when making requests - /// - protected ArrayParametersSerialization arraySerialization = ArrayParametersSerialization.Array; - - /// - /// What request body should be set when no data is send (only used in combination with postParametersPosition.InBody) - /// - protected string requestBodyEmptyContent = "{}"; - + /// public int TotalRequestsMade => ApiClients.OfType().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(request, deserializer, cancellationToken).ConfigureAwait(false); + return await GetResponseAsync(apiClient, request, deserializer, cancellationToken).ConfigureAwait(false); } /// /// Executes the request and returns the result deserialized into the type parameter class /// + /// The client making the request /// The request object to execute /// The JsonSerializer to use for deserialization /// Cancellation token /// - protected virtual async Task> GetResponseAsync(IRequest request, JsonSerializer? deserializer, CancellationToken cancellationToken) + protected virtual async Task> GetResponseAsync(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 /// /// Writes the parameters of the request to the request object body /// + /// The client making the request /// The request to set the parameters on /// The parameters to set /// The content type of the data - protected virtual void WriteParamBody(IRequest request, SortedDictionary parameters, string contentType) + protected virtual void WriteParamBody(BaseApiClient apiClient, IRequest request, SortedDictionary 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();