1
0
mirror of https://github.com/JKorf/CryptoExchange.Net.git synced 2026-08-11 16:32:57 +00:00

Added option to send additional headers for each request or for individual requests, added HttpMethod parameter position configuration to rest client

This commit is contained in:
Jkorf
2021-09-15 14:48:19 +02:00
parent f5df46a8a5
commit d1a2856a08
9 changed files with 203 additions and 196 deletions
@@ -10,6 +10,8 @@ using System.Linq;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.RateLimiter;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests
{
@@ -22,7 +24,7 @@ namespace CryptoExchange.Net.UnitTests
// arrange
var client = new TestRestClient();
var expected = new TestObject() { DecimalData = 1.23M, IntData = 10, StringData = "Some data" };
client.SetResponse(JsonConvert.SerializeObject(expected));
client.SetResponse(JsonConvert.SerializeObject(expected), out _);
// act
var result = client.Request<TestObject>().Result;
@@ -37,7 +39,7 @@ namespace CryptoExchange.Net.UnitTests
{
// arrange
var client = new TestRestClient();
client.SetResponse("{\"property\": 123");
client.SetResponse("{\"property\": 123", out _);
// act
var result = client.Request<TestObject>().Result;
@@ -119,6 +121,46 @@ namespace CryptoExchange.Net.UnitTests
Assert.IsTrue(client.RequestTimeout == TimeSpan.FromMinutes(1));
}
[TestCase("GET", HttpMethodParameterPosition.InUri)] // No need to test InBody for GET since thats not valid
[TestCase("POST", HttpMethodParameterPosition.InBody)]
[TestCase("POST", HttpMethodParameterPosition.InUri)]
[TestCase("DELETE", HttpMethodParameterPosition.InBody)]
[TestCase("DELETE", HttpMethodParameterPosition.InUri)]
[TestCase("PUT", HttpMethodParameterPosition.InUri)]
[TestCase("PUT", HttpMethodParameterPosition.InBody)]
public async Task Setting_Should_ResultInOptionsSet(string method, HttpMethodParameterPosition pos)
{
// arrange
// act
var client = new TestRestClient(new RestClientOptions("")
{
BaseAddress = "http://test.address.com",
});
client.SetParameterPosition(new HttpMethod(method), pos);
client.SetResponse("{}", out var request);
await client.RequestWithParams<TestObject>(new HttpMethod(method), new Dictionary<string, object>
{
{ "TestParam1", "Value1" },
{ "TestParam2", 2 },
},
new Dictionary<string, string>
{
{ "TestHeader", "123" }
});
// assert
Assert.AreEqual(request.Method, new HttpMethod(method));
Assert.AreEqual(request.Content?.Contains("TestParam1") == true, pos == HttpMethodParameterPosition.InBody);
Assert.AreEqual(request.Uri.ToString().Contains("TestParam1"), pos == HttpMethodParameterPosition.InUri);
Assert.AreEqual(request.Content?.Contains("TestParam2") == true, pos == HttpMethodParameterPosition.InBody);
Assert.AreEqual(request.Uri.ToString().Contains("TestParam2"), pos == HttpMethodParameterPosition.InUri);
Assert.AreEqual(request.GetHeaders().First().Key, "TestHeader");
Assert.IsTrue(request.GetHeaders().First().Value.Contains("123"));
}
[TestCase]
public void SettingRateLimitingBehaviourToFail_Should_FailLimitedRequests()
{
@@ -128,12 +170,12 @@ namespace CryptoExchange.Net.UnitTests
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Fail
});
client.SetResponse("{\"property\": 123}");
client.SetResponse("{\"property\": 123}", out _);
// act
var result1 = client.Request<TestObject>().Result;
client.SetResponse("{\"property\": 123}");
client.SetResponse("{\"property\": 123}", out _);
var result2 = client.Request<TestObject>().Result;
@@ -151,13 +193,13 @@ namespace CryptoExchange.Net.UnitTests
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Wait
});
client.SetResponse("{\"property\": 123}");
client.SetResponse("{\"property\": 123}", out _);
// act
var sw = Stopwatch.StartNew();
var result1 = client.Request<TestObject>().Result;
client.SetResponse("{\"property\": 123}"); // reset response stream
client.SetResponse("{\"property\": 123}", out _); // reset response stream
var result2 = client.Request<TestObject>().Result;
sw.Stop();
@@ -178,17 +220,17 @@ namespace CryptoExchange.Net.UnitTests
LogLevel = LogLevel.Debug,
ApiCredentials = new ApiCredentials("TestKey", "TestSecret")
});
client.SetResponse("{\"property\": 123}");
client.SetResponse("{\"property\": 123}", out _);
// act
var sw = Stopwatch.StartNew();
var result1 = client.Request<TestObject>().Result;
client.SetKey("TestKey2", "TestSecret2"); // set to different key
client.SetResponse("{\"property\": 123}"); // reset response stream
client.SetResponse("{\"property\": 123}", out _); // reset response stream
var result2 = client.Request<TestObject>().Result;
client.SetKey("TestKey", "TestSecret"); // set back to original key, should delay
client.SetResponse("{\"property\": 123}"); // reset response stream
client.SetResponse("{\"property\": 123}", out _); // reset response stream
var result3 = client.Request<TestObject>().Result;
sw.Stop();
@@ -38,12 +38,12 @@ namespace CryptoExchange.Net.UnitTests
{
}
public override Dictionary<string, string> AddAuthenticationToHeaders(string uri, HttpMethod method, Dictionary<string, object> parameters, bool signed, PostParameters postParameters, ArrayParametersSerialization arraySerialization)
public override Dictionary<string, string> AddAuthenticationToHeaders(string uri, HttpMethod method, Dictionary<string, object> parameters, bool signed, HttpMethodParameterPosition postParameters, ArrayParametersSerialization arraySerialization)
{
return base.AddAuthenticationToHeaders(uri, method, parameters, signed, postParameters, arraySerialization);
}
public override Dictionary<string, object> AddAuthenticationToParameters(string uri, HttpMethod method, Dictionary<string, object> parameters, bool signed, PostParameters postParameters, ArrayParametersSerialization arraySerialization)
public override Dictionary<string, object> AddAuthenticationToParameters(string uri, HttpMethod method, Dictionary<string, object> parameters, bool signed, HttpMethodParameterPosition postParameters, ArrayParametersSerialization arraySerialization)
{
return base.AddAuthenticationToParameters(uri, method, parameters, signed, postParameters, arraySerialization);
}
@@ -11,6 +11,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CryptoExchange.Net.Authentication;
using System.Collections.Generic;
namespace CryptoExchange.Net.UnitTests.TestImplementations
{
@@ -26,12 +27,17 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
RequestFactory = new Mock<IRequestFactory>().Object;
}
public void SetParameterPosition(HttpMethod method, HttpMethodParameterPosition position)
{
ParameterPositions[method] = position;
}
public void SetKey(string key, string secret)
{
SetAuthenticationProvider(new UnitTests.TestAuthProvider(new ApiCredentials(key, secret)));
}
public void SetResponse(string responseData, Stream requestStream = null)
public void SetResponse(string responseData, out IRequest requestObj)
{
var expectedBytes = Encoding.UTF8.GetBytes(responseData);
var responseStream = new MemoryStream();
@@ -42,13 +48,23 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
response.Setup(c => c.IsSuccessStatusCode).Returns(true);
response.Setup(c => c.GetResponseStreamAsync()).Returns(Task.FromResult((Stream)responseStream));
var headers = new Dictionary<string, IEnumerable<string>>();
var request = new Mock<IRequest>();
request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
request.Setup(c => c.GetResponseAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(response.Object));
request.Setup(c => c.SetContent(It.IsAny<string>(), It.IsAny<string>())).Callback(new Action<string, string>((content, type) => { request.Setup(r => r.Content).Returns(content); }));
request.Setup(c => c.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, val) => headers.Add(key, new List<string> { val }));
request.Setup(c => c.GetHeaders()).Returns(() => headers);
var factory = Mock.Get(RequestFactory);
factory.Setup(c => c.Create(It.IsAny<HttpMethod>(), It.IsAny<string>(), It.IsAny<int>()))
.Callback<HttpMethod, string, int>((method, uri, id) =>
{
request.Setup(a => a.Uri).Returns(new Uri(uri));
request.Setup(a => a.Method).Returns(method);
})
.Returns(request.Object);
requestObj = request.Object;
}
public void SetErrorWithoutResponse(HttpStatusCode code, string message)
@@ -75,12 +91,16 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
response.Setup(c => c.IsSuccessStatusCode).Returns(false);
response.Setup(c => c.GetResponseStreamAsync()).Returns(Task.FromResult((Stream)responseStream));
var headers = new Dictionary<string, IEnumerable<string>>();
var request = new Mock<IRequest>();
request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
request.Setup(c => c.GetResponseAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(response.Object));
request.Setup(c => c.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, val) => headers.Add(key, new List<string> { val }));
request.Setup(c => c.GetHeaders()).Returns(headers);
var factory = Mock.Get(RequestFactory);
factory.Setup(c => c.Create(It.IsAny<HttpMethod>(), It.IsAny<string>(), It.IsAny<int>()))
.Callback<HttpMethod, string, int>((method, uri, id) => request.Setup(a => a.Uri).Returns(new Uri(uri)))
.Returns(request.Object);
}
@@ -88,6 +108,11 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
{
return await SendRequestAsync<T>(new Uri("http://www.test.com"), HttpMethod.Get, ct);
}
public async Task<CallResult<T>> RequestWithParams<T>(HttpMethod method, Dictionary<string, object> parameters, Dictionary<string, string> headers) where T : class
{
return await SendRequestAsync<T>(new Uri("http://www.test.com"), method, default, parameters, additionalHeaders: headers);
}
}
public class TestAuthProvider : AuthenticationProvider