From 2ec764f8ec570b582e317defc9e3e636b2aed9ed Mon Sep 17 00:00:00 2001 From: JustArchi Date: Mon, 6 Jun 2022 23:28:35 +0200 Subject: [PATCH] Rewrite WebBrowser errors handling --- ArchiSteamFarm/Core/ASF.cs | 2 +- .../Web/Responses/BinaryResponse.cs | 10 +- .../Web/Responses/ObjectResponse.cs | 2 +- .../Web/Responses/StreamResponse.cs | 12 +- ArchiSteamFarm/Web/WebBrowser.cs | 287 ++++++++++-------- 5 files changed, 170 insertions(+), 143 deletions(-) diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index 94f5e0a60..6bfccab2b 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -301,7 +301,7 @@ public static class ASF { progressReporter.ProgressChanged -= OnProgressChanged; } - if (response == null) { + if (response?.Content == null) { return null; } diff --git a/ArchiSteamFarm/Web/Responses/BinaryResponse.cs b/ArchiSteamFarm/Web/Responses/BinaryResponse.cs index ce7ec3b86..347b2bf87 100644 --- a/ArchiSteamFarm/Web/Responses/BinaryResponse.cs +++ b/ArchiSteamFarm/Web/Responses/BinaryResponse.cs @@ -27,13 +27,11 @@ namespace ArchiSteamFarm.Web.Responses; public sealed class BinaryResponse : BasicResponse { [PublicAPI] - public IReadOnlyCollection Content => Bytes; + public IReadOnlyCollection? Content => Bytes; - private readonly byte[] Bytes; + private readonly byte[]? Bytes; - public BinaryResponse(BasicResponse basicResponse, byte[] bytes) : base(basicResponse) { - ArgumentNullException.ThrowIfNull(basicResponse); + public BinaryResponse(BasicResponse basicResponse, byte[] bytes) : this(basicResponse) => Bytes = bytes ?? throw new ArgumentNullException(nameof(bytes)); - Bytes = bytes ?? throw new ArgumentNullException(nameof(bytes)); - } + public BinaryResponse(BasicResponse basicResponse) : base(basicResponse) => ArgumentNullException.ThrowIfNull(basicResponse); } diff --git a/ArchiSteamFarm/Web/Responses/ObjectResponse.cs b/ArchiSteamFarm/Web/Responses/ObjectResponse.cs index 0f0d2edca..404293a06 100644 --- a/ArchiSteamFarm/Web/Responses/ObjectResponse.cs +++ b/ArchiSteamFarm/Web/Responses/ObjectResponse.cs @@ -28,7 +28,7 @@ public sealed class ObjectResponse : BasicResponse { [PublicAPI] public T? Content { get; } - public ObjectResponse(BasicResponse basicResponse, T? content) : this(basicResponse) => Content = content; + public ObjectResponse(BasicResponse basicResponse, T content) : this(basicResponse) => Content = content ?? throw new ArgumentNullException(nameof(content)); public ObjectResponse(BasicResponse basicResponse) : base(basicResponse) => ArgumentNullException.ThrowIfNull(basicResponse); } diff --git a/ArchiSteamFarm/Web/Responses/StreamResponse.cs b/ArchiSteamFarm/Web/Responses/StreamResponse.cs index d2524d786..f85151488 100644 --- a/ArchiSteamFarm/Web/Responses/StreamResponse.cs +++ b/ArchiSteamFarm/Web/Responses/StreamResponse.cs @@ -29,22 +29,24 @@ namespace ArchiSteamFarm.Web.Responses; public sealed class StreamResponse : BasicResponse, IAsyncDisposable { [PublicAPI] - public Stream Content { get; } + public Stream? Content { get; } [PublicAPI] public long Length { get; } private readonly HttpResponseMessage ResponseMessage; - internal StreamResponse(HttpResponseMessage httpResponseMessage, Stream content) : base(httpResponseMessage) { - ResponseMessage = httpResponseMessage ?? throw new ArgumentNullException(nameof(httpResponseMessage)); - Content = content ?? throw new ArgumentNullException(nameof(content)); + internal StreamResponse(HttpResponseMessage httpResponseMessage, Stream content) : this(httpResponseMessage) => Content = content ?? throw new ArgumentNullException(nameof(content)); + internal StreamResponse(HttpResponseMessage httpResponseMessage) : base(httpResponseMessage) { + ResponseMessage = httpResponseMessage ?? throw new ArgumentNullException(nameof(httpResponseMessage)); Length = httpResponseMessage.Content.Headers.ContentLength.GetValueOrDefault(); } public async ValueTask DisposeAsync() { - await Content.DisposeAsync().ConfigureAwait(false); + if (Content != null) { + await Content.DisposeAsync().ConfigureAwait(false); + } ResponseMessage.Dispose(); } diff --git a/ArchiSteamFarm/Web/WebBrowser.cs b/ArchiSteamFarm/Web/WebBrowser.cs index 1c64f4965..5fb1713dc 100644 --- a/ArchiSteamFarm/Web/WebBrowser.cs +++ b/ArchiSteamFarm/Web/WebBrowser.cs @@ -133,27 +133,34 @@ public sealed class WebBrowser : IDisposable { StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1, rateLimitingDelay).ConfigureAwait(false); - if (response == null) { + if (response?.Content == null) { // Request timed out, try again continue; } await using (response.ConfigureAwait(false)) { if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new BinaryResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new BinaryResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new BinaryResponse(response); } + + continue; } if (response.Length > Array.MaxLength) { @@ -213,10 +220,8 @@ public sealed class WebBrowser : IDisposable { } } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; } @@ -240,27 +245,34 @@ public sealed class WebBrowser : IDisposable { StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1, rateLimitingDelay).ConfigureAwait(false); - if (response == null) { + if (response?.Content == null) { // Request timed out, try again continue; } await using (response.ConfigureAwait(false)) { if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new HtmlDocumentResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new HtmlDocumentResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new HtmlDocumentResponse(response); } + + continue; } try { @@ -276,10 +288,8 @@ public sealed class WebBrowser : IDisposable { } } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; } @@ -303,27 +313,34 @@ public sealed class WebBrowser : IDisposable { StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1, rateLimitingDelay).ConfigureAwait(false); - if (response == null) { + if (response?.Content == null) { // Request timed out, try again continue; } await using (response.ConfigureAwait(false)) { if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new ObjectResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new ObjectResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new ObjectResponse(response); } + + continue; } T? obj; @@ -360,10 +377,8 @@ public sealed class WebBrowser : IDisposable { } } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; } @@ -393,29 +408,34 @@ public sealed class WebBrowser : IDisposable { } if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new StreamResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new StreamResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new StreamResponse(response); } + + continue; } return new StreamResponse(response, await response.Content.ReadAsStreamAsync().ConfigureAwait(false)); } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; } @@ -432,8 +452,6 @@ public sealed class WebBrowser : IDisposable { throw new ArgumentOutOfRangeException(nameof(rateLimitingDelay)); } - BasicResponse? result = null; - for (byte i = 0; i < maxTries; i++) { if ((i > 0) && (rateLimitingDelay > 0)) { await Task.Delay(rateLimitingDelay).ConfigureAwait(false); @@ -447,7 +465,7 @@ public sealed class WebBrowser : IDisposable { if (response.StatusCode.IsRedirectionCode()) { if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - result = new BasicResponse(response); + return new BasicResponse(response); } break; @@ -455,7 +473,7 @@ public sealed class WebBrowser : IDisposable { if (response.StatusCode.IsClientErrorCode()) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - result = new BasicResponse(response); + return new BasicResponse(response); } break; @@ -463,7 +481,7 @@ public sealed class WebBrowser : IDisposable { if (response.StatusCode.IsServerErrorCode()) { if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - result = new BasicResponse(response); + return new BasicResponse(response); } continue; @@ -472,12 +490,10 @@ public sealed class WebBrowser : IDisposable { return new BasicResponse(response); } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - return result; + return null; } [PublicAPI] @@ -492,8 +508,6 @@ public sealed class WebBrowser : IDisposable { throw new ArgumentOutOfRangeException(nameof(rateLimitingDelay)); } - BasicResponse? result = null; - for (byte i = 0; i < maxTries; i++) { if ((i > 0) && (rateLimitingDelay > 0)) { await Task.Delay(rateLimitingDelay).ConfigureAwait(false); @@ -507,7 +521,7 @@ public sealed class WebBrowser : IDisposable { if (response.StatusCode.IsRedirectionCode()) { if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - result = new BasicResponse(response); + return new BasicResponse(response); } break; @@ -515,7 +529,7 @@ public sealed class WebBrowser : IDisposable { if (response.StatusCode.IsClientErrorCode()) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - result = new BasicResponse(response); + return new BasicResponse(response); } break; @@ -523,7 +537,7 @@ public sealed class WebBrowser : IDisposable { if (response.StatusCode.IsServerErrorCode()) { if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - result = new BasicResponse(response); + return new BasicResponse(response); } continue; @@ -532,12 +546,10 @@ public sealed class WebBrowser : IDisposable { return new BasicResponse(response); } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - return result; + return null; } [PublicAPI] @@ -559,27 +571,34 @@ public sealed class WebBrowser : IDisposable { StreamResponse? response = await UrlPostToStream(request, headers, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1, rateLimitingDelay).ConfigureAwait(false); - if (response == null) { + if (response?.Content == null) { // Request timed out, try again continue; } await using (response.ConfigureAwait(false)) { if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new HtmlDocumentResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new HtmlDocumentResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new HtmlDocumentResponse(response); } + + continue; } try { @@ -595,10 +614,8 @@ public sealed class WebBrowser : IDisposable { } } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; } @@ -622,27 +639,34 @@ public sealed class WebBrowser : IDisposable { StreamResponse? response = await UrlPostToStream(request, headers, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1, rateLimitingDelay).ConfigureAwait(false); - if (response == null) { + if (response?.Content == null) { // Request timed out, try again continue; } await using (response.ConfigureAwait(false)) { if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new ObjectResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new ObjectResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new ObjectResponse(response); } + + continue; } TResult? obj; @@ -679,10 +703,8 @@ public sealed class WebBrowser : IDisposable { } } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; } @@ -712,29 +734,34 @@ public sealed class WebBrowser : IDisposable { } if (response.StatusCode.IsRedirectionCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { - // We're not handling this error, do not try again - break; + if (requestOptions.HasFlag(ERequestOptions.ReturnRedirections)) { + return new StreamResponse(response); } - } else if (response.StatusCode.IsClientErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - // We're not handling this error, do not try again - break; + + break; + } + + if (response.StatusCode.IsClientErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { + return new StreamResponse(response); } - } else if (response.StatusCode.IsServerErrorCode()) { - if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { - // We're not handling this error, try again - continue; + + break; + } + + if (response.StatusCode.IsServerErrorCode()) { + if (requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) { + return new StreamResponse(response); } + + continue; } return new StreamResponse(response, await response.Content.ReadAsStreamAsync().ConfigureAwait(false)); } - if (maxTries > 1) { - ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); - ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); - } + ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, maxTries)); + ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.ErrorFailingRequest, request)); return null; }