mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-12-14 01:33:26 +00:00
wip
This commit is contained in:
parent
839ebc4ca9
commit
fcef172069
@ -1,22 +1,22 @@
|
||||
using CryptoExchange.Net.Converters.MessageParsing;
|
||||
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
||||
using CryptoExchange.Net.Objects;
|
||||
using LightProto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
//using CryptoExchange.Net.Converters.MessageParsing;
|
||||
//using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
||||
//using CryptoExchange.Net.Objects;
|
||||
//using LightProto;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Net.WebSockets;
|
||||
//using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.Protobuf.Converters.Protobuf
|
||||
{
|
||||
public abstract class DynamicProtobufConverter<T> : ISocketMessageHandler
|
||||
{
|
||||
public object Deserialize(ReadOnlySpan<byte> data, Type type)
|
||||
{
|
||||
var result = Serializer.Deserialize<T>(data);
|
||||
return result;
|
||||
}
|
||||
//namespace CryptoExchange.Net.Protobuf.Converters.Protobuf
|
||||
//{
|
||||
// public abstract class DynamicProtobufConverter<T> : ISocketMessageHandler
|
||||
// {
|
||||
// public object Deserialize(ReadOnlySpan<byte> data, Type type)
|
||||
// {
|
||||
// var result = Serializer.Deserialize<T>(data);
|
||||
// return result;
|
||||
// }
|
||||
|
||||
public abstract string GetMessageIdentifier(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType);
|
||||
}
|
||||
}
|
||||
// public abstract string GetMessageIdentifier(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType);
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -4,11 +4,6 @@
|
||||
<name>CryptoExchange.Net.Protobuf</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="F:CryptoExchange.Net.Protobuf.Converters.Protobuf.DynamicProtobufConverter._model">
|
||||
<summary>
|
||||
Runtime type model
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CryptoExchange.Net.Converters.Protobuf.ProtobufMessageAccessor`1">
|
||||
<summary>
|
||||
System.Text.Json message accessor
|
||||
|
||||
@ -486,6 +486,10 @@ namespace CryptoExchange.Net.Clients
|
||||
memoryStream.Position = 0;
|
||||
originalData = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||
|
||||
if (_logger.IsEnabled(LogLevel.Trace))
|
||||
#warning TODO extension
|
||||
_logger.LogTrace("[Req {RequestId}] Received response: {Data}", request.RequestId, originalData);
|
||||
|
||||
// Continue processing from the memory stream since the response stream is already read and we can't seek it
|
||||
responseStream.Close();
|
||||
memoryStream.Position = 0;
|
||||
@ -494,9 +498,12 @@ namespace CryptoExchange.Net.Clients
|
||||
|
||||
if (!response.IsSuccessStatusCode && !requestDefinition.TryParseOnNonSuccess)
|
||||
{
|
||||
// If the response status is not success it is an error by definition
|
||||
|
||||
Error error;
|
||||
if (response.StatusCode == (HttpStatusCode)418 || response.StatusCode == (HttpStatusCode)429)
|
||||
{
|
||||
// Specifically handle rate limit errors
|
||||
var rateError = await MessageHandler.ParseErrorRateLimitResponse(
|
||||
(int)response.StatusCode,
|
||||
state,
|
||||
@ -512,6 +519,7 @@ namespace CryptoExchange.Net.Clients
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle a 'normal' error response. Can still be either a json error message or some random HTML or other string
|
||||
error = await MessageHandler.ParseErrorResponse(
|
||||
(int)response.StatusCode,
|
||||
state,
|
||||
@ -526,7 +534,7 @@ namespace CryptoExchange.Net.Clients
|
||||
// Success status code and expected empty response, assume it's correct
|
||||
return new WebCallResult<T>(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, 0, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, null);
|
||||
|
||||
// Data response received
|
||||
// Data response received, inspect the message and check if it is an error or not
|
||||
var parsedError = await MessageHandler.CheckForErrorResponse(
|
||||
requestDefinition,
|
||||
state,
|
||||
@ -547,8 +555,17 @@ namespace CryptoExchange.Net.Clients
|
||||
return new WebCallResult<T>(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, parsedError);
|
||||
}
|
||||
|
||||
// Try deserialization into the expected type
|
||||
var (deserializeResult, deserializeError) = await MessageHandler.TryDeserializeAsync<T>(responseStream, state, cancellationToken).ConfigureAwait(false);
|
||||
return new WebCallResult<T>(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, deserializeResult, deserializeError);
|
||||
if (deserializeError != null)
|
||||
return new WebCallResult<T>(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, deserializeResult, deserializeError); ;
|
||||
|
||||
// Check the deserialized response to see if it's an error or not
|
||||
var responseError = MessageHandler.CheckDeserializedResponse(response.ResponseHeaders, deserializeResult);
|
||||
if (responseError != null)
|
||||
return new WebCallResult<T>(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, deserializeResult, responseError);
|
||||
|
||||
return new WebCallResult<T>(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, deserializeResult, null);
|
||||
}
|
||||
catch (HttpRequestException requestException)
|
||||
{
|
||||
|
||||
@ -44,7 +44,10 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
Stream responseStream);
|
||||
|
||||
/// <summary>
|
||||
/// Check if the response is an error response; if so return the error
|
||||
/// Check if the response is an error response; if so return the error.<br />
|
||||
/// Note that if the API returns a standard result wrapper, something like this:
|
||||
/// <code>{ "code": 400, "msg": "error", "data": {} }</code>
|
||||
/// then the `CheckDeserializedResponse` method should be used for checking the result
|
||||
/// </summary>
|
||||
ValueTask<Error?> CheckForErrorResponse(
|
||||
RequestDefinition request,
|
||||
@ -59,6 +62,11 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
Stream responseStream,
|
||||
object? state,
|
||||
CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the resulting T object indicates an error or not
|
||||
/// </summary>
|
||||
Error? CheckDeserializedResponse<T>(HttpResponseHeaders responseHeaders, T result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -118,50 +118,19 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters
|
||||
result = await JsonSerializer.DeserializeAsync<T>(responseStream, Options)!.ConfigureAwait(false)!;
|
||||
}
|
||||
return (result, null);
|
||||
}
|
||||
catch (HttpRequestException requestException)
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
// Request exception, can't reach server for instance
|
||||
var error = new WebError(requestException.Message, requestException);
|
||||
return (default, error);
|
||||
var info = $"Json deserialization failed: {ex.Message}, Path: {ex.Path}, LineNumber: {ex.LineNumber}, LinePosition: {ex.BytePositionInLine}";
|
||||
return (default, new DeserializeError(info, ex));
|
||||
}
|
||||
catch (OperationCanceledException canceledException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (cancellationToken != default && canceledException.CancellationToken == cancellationToken)
|
||||
{
|
||||
// Cancellation token canceled by caller
|
||||
return (default, new CancellationRequestedError(canceledException));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Request timed out
|
||||
var error = new WebError($"Request timed out", exception: canceledException);
|
||||
error.ErrorType = ErrorType.Timeout;
|
||||
return (default, error);
|
||||
}
|
||||
}
|
||||
catch (ArgumentException argumentException)
|
||||
{
|
||||
if (argumentException.Message.StartsWith("Only HTTP/"))
|
||||
{
|
||||
// Unsupported HTTP version error .net framework
|
||||
var error = ArgumentError.Invalid(nameof(RestExchangeOptions.HttpVersion), $"Invalid HTTP version: " + argumentException.Message);
|
||||
return (default, error);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
catch (NotSupportedException notSupportedException)
|
||||
{
|
||||
if (notSupportedException.Message.StartsWith("Request version value must be one of"))
|
||||
{
|
||||
// Unsupported HTTP version error dotnet code
|
||||
var error = ArgumentError.Invalid(nameof(RestExchangeOptions.HttpVersion), $"Invalid HTTP version: " + notSupportedException.Message);
|
||||
return (default, error);
|
||||
}
|
||||
|
||||
throw;
|
||||
return (default, new DeserializeError($"Json deserialization failed: {ex.Message}", ex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Error? CheckDeserializedResponse<T>(HttpResponseHeaders responseHeaders, T result) => null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,11 +80,15 @@ namespace CryptoExchange.Net.Objects
|
||||
/// <summary>
|
||||
/// Get the parameter collection based on the ParameterPosition
|
||||
/// </summary>
|
||||
public IDictionary<string, object>? GetPositionParameters()
|
||||
public IDictionary<string, object> GetPositionParameters()
|
||||
{
|
||||
if (ParameterPosition == HttpMethodParameterPosition.InBody)
|
||||
{
|
||||
BodyParameters ??= new Dictionary<string, object>();
|
||||
return BodyParameters;
|
||||
}
|
||||
|
||||
QueryParameters ??= new Dictionary<string, object>();
|
||||
return QueryParameters;
|
||||
}
|
||||
|
||||
|
||||
@ -565,7 +565,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
if (deserializationType == null)
|
||||
{
|
||||
// No handler found for identifier either, can't process
|
||||
_logger.LogWarning("Failed to determine message type. Data: {Message}", Encoding.UTF8.GetString(data.ToArray()));
|
||||
_logger.LogWarning("Failed to determine message type for identifier {Identifier}. Data: {Message}", messageIdentifier, Encoding.UTF8.GetString(data.ToArray()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user