Обнновлено до .net10
This commit is contained in:
@@ -1,60 +1,56 @@
|
||||
using YandexMusic.API.Models.Common;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using YandexMusic.API.Models.Common;
|
||||
|
||||
namespace YandexMusic.API.Common.Providers
|
||||
namespace YandexMusic.API.Common.Providers;
|
||||
|
||||
/// <summary>Базовый провайдер HTTP-запросов с общей логикой десериализации.</summary>
|
||||
public abstract class CommonRequestProvider : IRequestProvider
|
||||
{
|
||||
public class CommonRequestProvider : IRequestProvider
|
||||
/// <summary>Хранилище данных авторизации.</summary>
|
||||
protected readonly AuthStorage storage;
|
||||
|
||||
/// <summary>Настройки сериализации JSON (регистронезависимые, поддержка enum-строк).</summary>
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
#region Поля
|
||||
PropertyNameCaseInsensitive = true,
|
||||
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
|
||||
};
|
||||
|
||||
protected AuthStorage storage;
|
||||
/// <summary>Инициализирует новый экземпляр провайдера.</summary>
|
||||
/// <param name="authStorage">Хранилище авторизации.</param>
|
||||
protected CommonRequestProvider(AuthStorage authStorage)
|
||||
{
|
||||
storage = authStorage;
|
||||
}
|
||||
|
||||
#endregion Поля
|
||||
/// <summary>Выполняет HTTP-запрос и возвращает ответ.</summary>
|
||||
public abstract Task<HttpResponseMessage> GetWebResponseAsync(
|
||||
HttpRequestMessage message,
|
||||
HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead);
|
||||
|
||||
/// <summary>Преобразует HTTP-ответ в объект типа T.</summary>
|
||||
public virtual async Task<T> GetDataFromResponseAsync<T>(
|
||||
YandexMusicApi api,
|
||||
HttpResponseMessage response)
|
||||
{
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
|
||||
|
||||
public CommonRequestProvider(AuthStorage authStorage)
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
storage = authStorage;
|
||||
var error = JsonSerializer.Deserialize<YErrorResponse>(json, JsonOptions);
|
||||
throw error ?? new Exception("Ошибка десериализации ответа с ошибкой.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region IRequestProvider
|
||||
|
||||
public virtual Task<HttpResponseMessage> GetWebResponseAsync(HttpRequestMessage message, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
|
||||
try
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// Если нужен контекст выполнения, он добавляется через кастомный конвертер
|
||||
return JsonSerializer.Deserialize<T>(json, JsonOptions)
|
||||
?? throw new JsonException("Десериализация вернула null");
|
||||
}
|
||||
|
||||
public virtual async Task<T> GetDataFromResponseAsync<T>(YandexMusicApi api, HttpResponseMessage response)
|
||||
catch (Exception ex)
|
||||
{
|
||||
string result = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
YErrorResponse exception = JsonConvert.DeserializeObject<YErrorResponse>(result);
|
||||
throw exception ?? new Exception("Ошибка десериализации ответа с ошибкой.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
JsonSerializerSettings settings = new()
|
||||
{
|
||||
Converters = new List<JsonConverter> {
|
||||
new YExecutionContextConverter(api, storage)
|
||||
}
|
||||
};
|
||||
|
||||
return storage.Debug != null
|
||||
? storage.Debug.Deserialize<T>(response.RequestMessage?.RequestUri?.AbsolutePath, result, settings)
|
||||
: JsonConvert.DeserializeObject<T>(result, settings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Ошибка десериализации {ex}");
|
||||
}
|
||||
throw new Exception($"Ошибка десериализации: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
#endregion IRequestProvider
|
||||
}
|
||||
}
|
||||
@@ -1,69 +1,45 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Models.Common;
|
||||
namespace YandexMusic.API.Common.Providers;
|
||||
|
||||
namespace YandexMusic.API.Common.Providers
|
||||
/// <summary>Стандартный провайдер HTTP-запросов с использованием HttpClient.</summary>
|
||||
public class DefaultRequestProvider : CommonRequestProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Стандартный провайдер запросов
|
||||
/// </summary>
|
||||
public class DefaultRequestProvider : CommonRequestProvider
|
||||
/// <summary>Инициализирует новый экземпляр провайдера.</summary>
|
||||
/// <param name="authStorage">Хранилище авторизации.</param>
|
||||
public DefaultRequestProvider(AuthStorage authStorage) : base(authStorage) { }
|
||||
|
||||
/// <summary>Выполняет HTTP-запрос и возвращает ответ.</summary>
|
||||
/// <param name="message">HTTP-запрос.</param>
|
||||
/// <param name="completionOption">Опция завершения запроса.</param>
|
||||
/// <returns>HTTP-ответ.</returns>
|
||||
public override async Task<HttpResponseMessage> GetWebResponseAsync(
|
||||
HttpRequestMessage message,
|
||||
HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
|
||||
{
|
||||
#region Вспомогательные функции
|
||||
|
||||
private Exception ProcessException(Exception ex)
|
||||
using var handler = new SocketsHttpHandler
|
||||
{
|
||||
if (ex is not WebException webException)
|
||||
return ex;
|
||||
Proxy = storage.Context.WebProxy,
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
|
||||
UseCookies = true,
|
||||
CookieContainer = storage.Context.Cookies,
|
||||
AllowAutoRedirect = true,
|
||||
MaxAutomaticRedirections = 10
|
||||
};
|
||||
|
||||
if (webException.Response is null)
|
||||
return ex;
|
||||
using var client = new HttpClient(handler);
|
||||
|
||||
Stream s = webException.Response.GetResponseStream();
|
||||
if (s is null)
|
||||
return ex;
|
||||
|
||||
using StreamReader sr = new(s);
|
||||
string result = sr.ReadToEnd();
|
||||
|
||||
YErrorResponse exception = JsonConvert.DeserializeObject<YErrorResponse>(result);
|
||||
|
||||
return exception ?? ex;
|
||||
}
|
||||
|
||||
#endregion Вспомогательные функции
|
||||
|
||||
|
||||
|
||||
public DefaultRequestProvider(AuthStorage authStorage) : base(authStorage)
|
||||
try
|
||||
{
|
||||
return await client.SendAsync(message, completionOption);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region IRequestProvider
|
||||
|
||||
public override Task<HttpResponseMessage> GetWebResponseAsync(HttpRequestMessage message,
|
||||
HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpClient client = new(new SocketsHttpHandler
|
||||
{
|
||||
Proxy = storage.Context.WebProxy,
|
||||
AutomaticDecompression = DecompressionMethods.GZip,
|
||||
UseCookies = true,
|
||||
CookieContainer = storage.Context.Cookies,
|
||||
});
|
||||
// Пытаемся извлечь тело ошибки, если оно доступно
|
||||
if (ex.InnerException == null)
|
||||
throw;
|
||||
|
||||
return client.SendAsync(message, completionOption);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ProcessException(ex);
|
||||
}
|
||||
throw new Exception($"Ошибка HTTP-запроса: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
#endregion IRequestProvider
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
public MockRequestProvider(AuthStorage authStorage) : base(authStorage)
|
||||
{
|
||||
storage = authStorage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user