diff --git a/CryptoExchange.Net.UnitTests/TestImplementation.cs b/CryptoExchange.Net.UnitTests/TestImplementation.cs index e2dd2b1..f0a0ec6 100644 --- a/CryptoExchange.Net.UnitTests/TestImplementation.cs +++ b/CryptoExchange.Net.UnitTests/TestImplementation.cs @@ -31,14 +31,14 @@ namespace CryptoExchange.Net.UnitTests { } - public override string AddAuthenticationToUriString(string uri, bool signed) + public override Dictionary AddAuthenticationToHeaders(string uri, string method, Dictionary parameters, bool signed) { - return uri; + return base.AddAuthenticationToHeaders(uri, method, parameters, signed); } - public override IRequest AddAuthenticationToRequest(IRequest request, bool signed) + public override Dictionary AddAuthenticationToParameters(string uri, string method, Dictionary parameters, bool signed) { - return request; + return base.AddAuthenticationToParameters(uri, method, parameters, signed); } public override string Sign(string toSign) diff --git a/CryptoExchange.Net/Authentication/AuthenticationProvider.cs b/CryptoExchange.Net/Authentication/AuthenticationProvider.cs index 4dd1431..9ff76e3 100644 --- a/CryptoExchange.Net/Authentication/AuthenticationProvider.cs +++ b/CryptoExchange.Net/Authentication/AuthenticationProvider.cs @@ -1,4 +1,5 @@ using CryptoExchange.Net.Interfaces; +using System.Collections.Generic; namespace CryptoExchange.Net.Authentication { @@ -11,14 +12,14 @@ namespace CryptoExchange.Net.Authentication Credentials = credentials; } - public virtual string AddAuthenticationToUriString(string uri, bool signed) + public virtual Dictionary AddAuthenticationToParameters(string uri, string method, Dictionary parameters, bool signed) { - return uri; + return parameters; } - public virtual IRequest AddAuthenticationToRequest(IRequest request, bool signed) + public virtual Dictionary AddAuthenticationToHeaders(string uri, string method, Dictionary parameters, bool signed) { - return request; + return new Dictionary(); } public virtual string Sign(string toSign) diff --git a/CryptoExchange.Net/ExchangeClient.cs b/CryptoExchange.Net/ExchangeClient.cs index bd4cd16..1e06903 100644 --- a/CryptoExchange.Net/ExchangeClient.cs +++ b/CryptoExchange.Net/ExchangeClient.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; +using System.Text; using System.Threading.Tasks; using CryptoExchange.Net.Attributes; using CryptoExchange.Net.Authentication; @@ -28,6 +29,8 @@ namespace CryptoExchange.Net protected ApiProxy apiProxy; protected RateLimitingBehaviour rateLimitBehaviour; + protected PostParameters postParametersPosition = PostParameters.InBody; + protected AuthenticationProvider authProvider; private List rateLimiters; @@ -165,42 +168,57 @@ namespace CryptoExchange.Net paramString = paramString.Trim(','); } - log.Write(LogVerbosity.Debug, $"Sending {(signed ? "signed" : "")} request to {request.Uri} {(paramString ?? "")}"); + log.Write(LogVerbosity.Debug, $"Sending {method} {(signed ? "signed" : "")} request to {request.Uri} {(paramString ?? "")}"); var result = await ExecuteRequest(request).ConfigureAwait(false); return result.Error != null ? new CallResult(null, result.Error) : Deserialize(result.Data); } protected virtual IRequest ConstructRequest(Uri uri, string method, Dictionary parameters, bool signed) { + if (parameters == null) + parameters = new Dictionary(); + var uriString = uri.ToString(); + parameters = authProvider.AddAuthenticationToParameters(uriString, method, parameters, signed); - if (parameters != null) - { - if (!uriString.EndsWith("?")) - uriString += "?"; - - var arraysParameters = parameters.Where(p => p.Value.GetType().IsArray).ToList(); - foreach(var arrayEntry in arraysParameters) - { - uriString += $"{string.Join("&", ((object[])arrayEntry.Value).Select(v => $"{arrayEntry.Key}[]={v}"))}&"; - } - - uriString += $"{string.Join("&", parameters.Where(p => !p.Value.GetType().IsArray).Select(s => $"{s.Key}={s.Value}"))}"; - uriString = uriString.TrimEnd('&'); - } - - if (authProvider != null) - uriString = authProvider.AddAuthenticationToUriString(uriString, signed); - + if((method == "GET" || method == "DELETE" || ((method == "POST" || method == "PUT") && postParametersPosition == PostParameters.InUri)) && parameters?.Any() == true) + uriString += parameters.CreateParamString(); + var request = RequestFactory.Create(uriString); + request.ContentType = "application/json"; + request.Accept = "application/json"; request.Method = method; - if (authProvider != null) - request = authProvider.AddAuthenticationToRequest(request, signed); + var headers = authProvider.AddAuthenticationToHeaders(uriString, method, parameters, signed); + foreach (var header in headers) + request.Headers.Add(header.Key, header.Value); + + if ((method == "POST" || method == "PUT") && postParametersPosition != PostParameters.InUri) + { + if(parameters?.Any() == true) + WriteParamBody(request, parameters); + else + WriteParamBody(request, "{}"); + } return request; } + protected void WriteParamBody(IRequest request, string stringData) + { + var data = Encoding.UTF8.GetBytes(stringData); + request.ContentLength = data.Length; + + using (var stream = request.GetRequestStream().Result) + stream.Write(data, 0, data.Length); + } + + protected void WriteParamBody(IRequest request, Dictionary parameters) + { + var stringData = JsonConvert.SerializeObject(parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value)); + WriteParamBody(request, stringData); + } + private async Task> ExecuteRequest(IRequest request) { var returnedData = ""; diff --git a/CryptoExchange.Net/ExtensionMethods.cs b/CryptoExchange.Net/ExtensionMethods.cs index 673def1..3e6d6b9 100644 --- a/CryptoExchange.Net/ExtensionMethods.cs +++ b/CryptoExchange.Net/ExtensionMethods.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.InteropServices; using System.Security; @@ -29,6 +30,20 @@ namespace CryptoExchange.Net parameters.Add(key, value); } + public static string CreateParamString(this Dictionary parameters) + { + var uriString = "?"; + var arraysParameters = parameters.Where(p => p.Value.GetType().IsArray).ToList(); + foreach (var arrayEntry in arraysParameters) + { + uriString += $"{string.Join("&", ((object[])arrayEntry.Value).Select(v => $"{arrayEntry.Key}[]={v}"))}&"; + } + + uriString += $"{string.Join("&", parameters.Where(p => !p.Value.GetType().IsArray).Select(s => $"{s.Key}={s.Value}"))}"; + uriString = uriString.TrimEnd('&'); + return uriString; + } + public static string GetString(this SecureString source) { lock (source) diff --git a/CryptoExchange.Net/Objects/Enums.cs b/CryptoExchange.Net/Objects/Enums.cs index ba0f75c..ccf0287 100644 --- a/CryptoExchange.Net/Objects/Enums.cs +++ b/CryptoExchange.Net/Objects/Enums.cs @@ -5,4 +5,10 @@ Fail, Wait } + + public enum PostParameters + { + InBody, + InUri + } }