This commit is contained in:
DismissedLight
2024-07-16 17:30:25 +08:00
parent 2c139a1ff6
commit 84e05017ba
5 changed files with 117 additions and 48 deletions

View File

@@ -3,26 +3,12 @@
namespace Snap.Hutao.Model.Calculable; namespace Snap.Hutao.Model.Calculable;
/// <summary>
/// 可计算物品选项
/// </summary>
internal readonly struct CalculableOptions internal readonly struct CalculableOptions
{ {
/// <summary>
/// 角色
/// </summary>
public readonly ICalculableAvatar? Avatar; public readonly ICalculableAvatar? Avatar;
/// <summary>
/// 武器
/// </summary>
public readonly ICalculableWeapon? Weapon; public readonly ICalculableWeapon? Weapon;
/// <summary>
/// 构造一个新的可计算物品选项
/// </summary>
/// <param name="avatar">角色</param>
/// <param name="weapon">武器</param>
public CalculableOptions(ICalculableAvatar? avatar, ICalculableWeapon? weapon) public CalculableOptions(ICalculableAvatar? avatar, ICalculableWeapon? weapon)
{ {
Avatar = avatar; Avatar = avatar;

View File

@@ -228,7 +228,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
.ConfigureAwait(false); .ConfigureAwait(false);
// We have a verification procedure to handle // We have a verification procedure to handle
if (resp?.ReturnCode == (int)KnownReturnCode.CODE1034) if (resp?.ReturnCode is (int)KnownReturnCode.CODE1034)
{ {
// Replace message // Replace message
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed; resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;

View File

@@ -8,7 +8,7 @@ using System.Net.Http.Headers;
namespace Snap.Hutao.Web.Request.Builder; namespace Snap.Hutao.Web.Request.Builder;
internal class HttpRequestMessageBuilder : internal sealed class HttpRequestMessageBuilder :
IBuilder, IBuilder,
IHttpRequestMessageBuilder, IHttpRequestMessageBuilder,
IHttpHeadersBuilder<HttpHeaders>, IHttpHeadersBuilder<HttpHeaders>,
@@ -22,12 +22,14 @@ internal class HttpRequestMessageBuilder :
IHttpMethodBuilder IHttpMethodBuilder
{ {
private readonly HttpContentSerializer httpContentSerializer; private readonly HttpContentSerializer httpContentSerializer;
private readonly IServiceProvider serviceProvider;
private HttpRequestMessage httpRequestMessage; private HttpRequestMessage httpRequestMessage;
public HttpRequestMessageBuilder(HttpContentSerializer httpContentSerializer, HttpRequestMessage? httpRequestMessage = default) public HttpRequestMessageBuilder(IServiceProvider serviceProvider, HttpContentSerializer httpContentSerializer, HttpRequestMessage? httpRequestMessage = default)
{ {
this.serviceProvider = serviceProvider;
this.httpContentSerializer = httpContentSerializer; this.httpContentSerializer = httpContentSerializer;
this.httpRequestMessage = httpRequestMessage ?? new HttpRequestMessage(); this.httpRequestMessage = httpRequestMessage ?? new();
} }
public HttpRequestMessage HttpRequestMessage public HttpRequestMessage HttpRequestMessage
@@ -40,6 +42,8 @@ internal class HttpRequestMessageBuilder :
} }
} }
public IServiceProvider ServiceProvider { get => serviceProvider; }
public HttpContentSerializer HttpContentSerializer { get => httpContentSerializer; } public HttpContentSerializer HttpContentSerializer { get => httpContentSerializer; }
HttpContentHeaders IHttpHeadersBuilder<HttpContentHeaders>.Headers HttpContentHeaders IHttpHeadersBuilder<HttpContentHeaders>.Headers

View File

@@ -1,11 +1,14 @@
// Copyright (c) DGP Studio. All rights reserved. // Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license. // Licensed under the MIT license.
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Web.Hutao.Response; using Snap.Hutao.Web.Hutao.Response;
using Snap.Hutao.Web.Response;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text;
namespace Snap.Hutao.Web.Request.Builder; namespace Snap.Hutao.Web.Request.Builder;
@@ -22,6 +25,10 @@ internal static class HttpRequestMessageBuilderExtension
internal static async ValueTask<TResult?> SendAsync<TResult>(this HttpRequestMessageBuilder builder, HttpClient httpClient, ILogger logger, CancellationToken token) internal static async ValueTask<TResult?> SendAsync<TResult>(this HttpRequestMessageBuilder builder, HttpClient httpClient, ILogger logger, CancellationToken token)
where TResult : class where TResult : class
{ {
StringBuilder messageBuilder = new();
messageBuilder.AppendLine(System.Globalization.CultureInfo.CurrentCulture, $"Host: {builder.RequestUri?.Host}");
bool showInfo = true;
try try
{ {
using (builder.HttpRequestMessage) using (builder.HttpRequestMessage)
@@ -29,51 +36,50 @@ internal static class HttpRequestMessageBuilderExtension
using (HttpResponseMessage message = await httpClient.SendAsync(builder.HttpRequestMessage, token).ConfigureAwait(false)) using (HttpResponseMessage message = await httpClient.SendAsync(builder.HttpRequestMessage, token).ConfigureAwait(false))
{ {
message.EnsureSuccessStatusCode(); message.EnsureSuccessStatusCode();
return await builder.HttpContentSerializer.DeserializeAsync<TResult>(message.Content, token).ConfigureAwait(false); showInfo = false;
return result = await builder.HttpContentSerializer.DeserializeAsync<TResult>(message.Content, token).ConfigureAwait(false);
} }
} }
} }
catch (HttpRequestException ex) catch (HttpRequestException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); if (TryHandleHttp502HutaoResponseSpecialCase(ex, out TResult? result))
if (ex.StatusCode is HttpStatusCode.BadGateway)
{ {
Type resultType = typeof(TResult); return result;
if (resultType == typeof(HutaoResponse))
{
return Activator.CreateInstance(resultType, 502, SH.WebHutaoServiceUnAvailable, default) as TResult;
} }
if (resultType.IsConstructedGenericType && resultType.GetGenericTypeDefinition() == typeof(HutaoResponse<>)) ProcessException(messageBuilder, ex);
{ logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
return Activator.CreateInstance(resultType, 502, SH.WebHutaoServiceUnAvailable, default, default) as TResult;
}
}
return default;
} }
catch (IOException ex) catch (IOException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); ProcessException(messageBuilder, ex);
return default; logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (JsonException ex) catch (JsonException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); ProcessException(messageBuilder, ex);
return default; logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (HttpContentSerializationException ex) catch (HttpContentSerializationException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); ProcessException(messageBuilder, ex);
return default; logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (SocketException ex) catch (SocketException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); ProcessException(messageBuilder, ex);
return default; logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
finally
{
if (showInfo)
{
builder.ServiceProvider.GetRequiredService<IInfoBarService>().Error(messageBuilder.ToString());
}
}
return default;
} }
internal static void Send(this HttpRequestMessageBuilder builder, HttpClient httpClient, ILogger logger) internal static void Send(this HttpRequestMessageBuilder builder, HttpClient httpClient, ILogger logger)
@@ -86,23 +92,95 @@ internal static class HttpRequestMessageBuilderExtension
} }
catch (HttpRequestException ex) catch (HttpRequestException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (IOException ex) catch (IOException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (JsonException ex) catch (JsonException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (HttpContentSerializationException ex) catch (HttpContentSerializationException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
} }
catch (SocketException ex) catch (SocketException ex)
{ {
logger.LogWarning(ex, RequestErrorMessage, builder.HttpRequestMessage.RequestUri); logger.LogWarning(ex, RequestErrorMessage, builder.RequestUri);
}
}
private static bool TryHandleHttp502HutaoResponseSpecialCase<TResult>(HttpRequestException ex, out TResult? result)
where TResult : class
{
result = default;
if (ex.StatusCode is HttpStatusCode.BadGateway)
{
Type resultType = typeof(TResult);
if (resultType == typeof(HutaoResponse))
{
// HutaoResponse(int returnCode, string message, string? localizationKey)
result = Activator.CreateInstance(resultType, 502, SH.WebHutaoServiceUnAvailable, default) as TResult;
return true;
}
if (resultType.IsConstructedGenericType && resultType.GetGenericTypeDefinition() == typeof(HutaoResponse<>))
{
// HutaoResponse<TData>(int returnCode, string message, TData? data, string? localizationKey)
result = Activator.CreateInstance(resultType, 502, SH.WebHutaoServiceUnAvailable, default, default) as TResult;
return true;
}
}
return false;
}
[SuppressMessage("", "CA1305")]
private static void ProcessException(StringBuilder builder, Exception exception)
{
if (exception is HttpRequestException hre)
{
builder
.AppendLine($"{nameof(HttpRequestException)}: Status Code: {hre.StatusCode} Error: {hre.HttpRequestError}")
.AppendLine(hre.Message);
}
if (exception is IOException ioe)
{
builder
.AppendLine($"{nameof(IOException)}: 0x{ioe.HResult:X8}")
.AppendLine(ioe.Message);
}
if (exception is JsonException je)
{
builder
.AppendLine($"{nameof(JsonException)}: Path: {je.Path} at Line: {je.LineNumber} Position: {je.BytePositionInLine}")
.AppendLine(je.Message);
}
if (exception is HttpContentSerializationException hcse)
{
builder
.AppendLine($"{nameof(HttpContentSerializationException)}:")
.AppendLine(hcse.Message);
}
if (exception is SocketException se)
{
builder
.AppendLine($"{nameof(SocketException)}: Error: {se.SocketErrorCode}")
.AppendLine(se.Message);
}
if (exception.InnerException is { } inner)
{
builder.AppendLine(new string('-', 40));
ProcessException(builder, inner);
} }
} }
} }

View File

@@ -10,9 +10,10 @@ namespace Snap.Hutao.Web.Request.Builder;
internal sealed partial class HttpRequestMessageBuilderFactory : IHttpRequestMessageBuilderFactory internal sealed partial class HttpRequestMessageBuilderFactory : IHttpRequestMessageBuilderFactory
{ {
private readonly JsonHttpContentSerializer jsonHttpContentSerializer; private readonly JsonHttpContentSerializer jsonHttpContentSerializer;
private readonly IServiceProvider serviceProvider;
public HttpRequestMessageBuilder Create() public HttpRequestMessageBuilder Create()
{ {
return new(jsonHttpContentSerializer); return new(serviceProvider, jsonHttpContentSerializer);
} }
} }