From 258949c0aa5fe53f912155152c3acd84d53fcf98 Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Sat, 16 Dec 2023 14:36:31 -0600 Subject: [PATCH] refactor: Upgrade Flurl to v4.0.0 Required refactoring the way before/after/redirect handlers were implemented. --- Directory.Packages.props | 2 +- .../ApiServicesAutofacModule.cs | 7 +++ .../CustomFormat/CustomFormatApiService.cs | 2 +- src/Recyclarr.ServarrApi/Http/FlurlLogging.cs | 39 +------------ .../Http/FlurlSpecificEventHandler.cs | 11 ++++ .../{ => Servarr}/IServarrRequestBuilder.cs | 2 +- .../Http/Servarr/ServarrFlurlEventHandlers.cs | 55 +++++++++++++++++++ .../{ => Servarr}/ServarrRequestBuilder.cs | 11 +++- .../MediaNaming/MediaNamingApiService.cs | 2 +- .../QualityDefinitionApiService.cs | 2 +- .../QualityProfileApiService.cs | 2 +- .../ReleaseProfileApiService.cs | 2 +- .../System/SystemApiService.cs | 2 +- .../Tag/SonarrTagApiService.cs | 2 +- 14 files changed, 91 insertions(+), 50 deletions(-) create mode 100644 src/Recyclarr.ServarrApi/Http/FlurlSpecificEventHandler.cs rename src/Recyclarr.ServarrApi/Http/{ => Servarr}/IServarrRequestBuilder.cs (79%) create mode 100644 src/Recyclarr.ServarrApi/Http/Servarr/ServarrFlurlEventHandlers.cs rename src/Recyclarr.ServarrApi/Http/{ => Servarr}/ServarrRequestBuilder.cs (84%) diff --git a/Directory.Packages.props b/Directory.Packages.props index b987d47c..20d604e4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + diff --git a/src/Recyclarr.ServarrApi/ApiServicesAutofacModule.cs b/src/Recyclarr.ServarrApi/ApiServicesAutofacModule.cs index 19247afc..9bb4831a 100644 --- a/src/Recyclarr.ServarrApi/ApiServicesAutofacModule.cs +++ b/src/Recyclarr.ServarrApi/ApiServicesAutofacModule.cs @@ -2,6 +2,7 @@ using Autofac; using Flurl.Http.Configuration; using Recyclarr.ServarrApi.CustomFormat; using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; using Recyclarr.ServarrApi.MediaNaming; using Recyclarr.ServarrApi.QualityDefinition; using Recyclarr.ServarrApi.QualityProfile; @@ -26,5 +27,11 @@ public class ApiServicesAutofacModule : Module builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); + + builder.RegisterTypes( + typeof(FlurlAfterCallHandler), + typeof(FlurlBeforeCallHandler), + typeof(FlurlRedirectHandler)) + .As(); } } diff --git a/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs b/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs index 3fb26cd6..7db5681d 100644 --- a/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs +++ b/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs @@ -1,6 +1,6 @@ using Flurl.Http; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; using Recyclarr.TrashGuide.CustomFormat; namespace Recyclarr.ServarrApi.CustomFormat; diff --git a/src/Recyclarr.ServarrApi/Http/FlurlLogging.cs b/src/Recyclarr.ServarrApi/Http/FlurlLogging.cs index 42abd18a..82073fb7 100644 --- a/src/Recyclarr.ServarrApi/Http/FlurlLogging.cs +++ b/src/Recyclarr.ServarrApi/Http/FlurlLogging.cs @@ -1,49 +1,12 @@ using System.Text.Json; using Flurl; -using Flurl.Http.Configuration; using Serilog; namespace Recyclarr.ServarrApi.Http; public static class FlurlLogging { - public static void SetupLogging(FlurlHttpSettings settings, ILogger log, Func? urlInterceptor = null) - { - urlInterceptor ??= SanitizeUrl; - - settings.BeforeCall = call => - { - var url = urlInterceptor(call.Request.Url.Clone()); - log.Debug("HTTP Request: {Method} {Url}", call.HttpRequestMessage.Method, url); - LogBody(log, url, "Request", call.HttpRequestMessage.Method, call.RequestBody); - }; - - settings.AfterCallAsync = async call => - { - var statusCode = call.Response?.StatusCode.ToString() ?? "(No response)"; - var url = urlInterceptor(call.Request.Url.Clone()); - log.Debug("HTTP Response: {Status} {Method} {Url}", statusCode, call.HttpRequestMessage.Method, url); - - var content = call.Response?.ResponseMessage.Content; - if (content is not null) - { - LogBody(log, url, "Response", call.HttpRequestMessage.Method, await content.ReadAsStringAsync()); - } - }; - - settings.OnRedirect = call => - { - log.Warning("HTTP Redirect received; this indicates a problem with your URL and/or reverse proxy: {Url}", - urlInterceptor(call.Redirect.Url)); - - // Must follow redirect because we want an exception to be thrown eventually. If it is set to false, HTTP - // communication stops and existing methods will return nothing / null. This messes with Observable - // pipelines (which normally either expect a response object or an exception) - call.Redirect.Follow = true; - }; - } - - private static void LogBody(ILogger log, Url url, string direction, HttpMethod method, string? body) + public static void LogBody(ILogger log, Url url, string direction, HttpMethod method, string? body) { if (string.IsNullOrEmpty(body)) { diff --git a/src/Recyclarr.ServarrApi/Http/FlurlSpecificEventHandler.cs b/src/Recyclarr.ServarrApi/Http/FlurlSpecificEventHandler.cs new file mode 100644 index 00000000..b07ac24f --- /dev/null +++ b/src/Recyclarr.ServarrApi/Http/FlurlSpecificEventHandler.cs @@ -0,0 +1,11 @@ +using System.Diagnostics.CodeAnalysis; +using Flurl.Http; + +namespace Recyclarr.ServarrApi.Http; + +[SuppressMessage("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = + "Naming convention borrowed from and determined by Flurl")] +public abstract class FlurlSpecificEventHandler : FlurlEventHandler +{ + public abstract FlurlEventType EventType { get; } +} diff --git a/src/Recyclarr.ServarrApi/Http/IServarrRequestBuilder.cs b/src/Recyclarr.ServarrApi/Http/Servarr/IServarrRequestBuilder.cs similarity index 79% rename from src/Recyclarr.ServarrApi/Http/IServarrRequestBuilder.cs rename to src/Recyclarr.ServarrApi/Http/Servarr/IServarrRequestBuilder.cs index 928981ff..1a3d3f1b 100644 --- a/src/Recyclarr.ServarrApi/Http/IServarrRequestBuilder.cs +++ b/src/Recyclarr.ServarrApi/Http/Servarr/IServarrRequestBuilder.cs @@ -1,7 +1,7 @@ using Flurl.Http; using Recyclarr.Config.Models; -namespace Recyclarr.ServarrApi.Http; +namespace Recyclarr.ServarrApi.Http.Servarr; public interface IServarrRequestBuilder { diff --git a/src/Recyclarr.ServarrApi/Http/Servarr/ServarrFlurlEventHandlers.cs b/src/Recyclarr.ServarrApi/Http/Servarr/ServarrFlurlEventHandlers.cs new file mode 100644 index 00000000..fa7f527b --- /dev/null +++ b/src/Recyclarr.ServarrApi/Http/Servarr/ServarrFlurlEventHandlers.cs @@ -0,0 +1,55 @@ +using Flurl.Http; +using JetBrains.Annotations; +using Serilog; + +namespace Recyclarr.ServarrApi.Http.Servarr; + +[UsedImplicitly] +public class FlurlBeforeCallHandler(ILogger log) : FlurlSpecificEventHandler +{ + public override FlurlEventType EventType => FlurlEventType.BeforeCall; + + public override void Handle(FlurlEventType eventType, FlurlCall call) + { + var url = FlurlLogging.SanitizeUrl(call.Request.Url.Clone()); + log.Debug("HTTP Request: {Method} {Url}", call.HttpRequestMessage.Method, url); + FlurlLogging.LogBody(log, url, "Request", call.HttpRequestMessage.Method, call.RequestBody); + } +} + +[UsedImplicitly] +public class FlurlAfterCallHandler(ILogger log) : FlurlSpecificEventHandler +{ + public override FlurlEventType EventType => FlurlEventType.AfterCall; + + public override async Task HandleAsync(FlurlEventType eventType, FlurlCall call) + { + var statusCode = call.Response?.StatusCode.ToString() ?? "(No response)"; + var url = FlurlLogging.SanitizeUrl(call.Request.Url.Clone()); + log.Debug("HTTP Response: {Status} {Method} {Url}", statusCode, call.HttpRequestMessage.Method, url); + + var content = call.Response?.ResponseMessage.Content; + if (content is not null) + { + FlurlLogging.LogBody(log, url, "Response", call.HttpRequestMessage.Method, + await content.ReadAsStringAsync()); + } + } +} + +[UsedImplicitly] +public class FlurlRedirectHandler(ILogger log) : FlurlSpecificEventHandler +{ + public override FlurlEventType EventType => FlurlEventType.OnRedirect; + + public override void Handle(FlurlEventType eventType, FlurlCall call) + { + log.Warning("HTTP Redirect received; this indicates a problem with your URL and/or reverse proxy: {Url}", + FlurlLogging.SanitizeUrl(call.Redirect.Url)); + + // Must follow redirect because we want an exception to be thrown eventually. If it is set to false, HTTP + // communication stops and existing methods will return nothing / null. This messes with Observable + // pipelines (which normally either expect a response object or an exception) + call.Redirect.Follow = true; + } +} diff --git a/src/Recyclarr.ServarrApi/Http/ServarrRequestBuilder.cs b/src/Recyclarr.ServarrApi/Http/Servarr/ServarrRequestBuilder.cs similarity index 84% rename from src/Recyclarr.ServarrApi/Http/ServarrRequestBuilder.cs rename to src/Recyclarr.ServarrApi/Http/Servarr/ServarrRequestBuilder.cs index c9c79499..62d5c20d 100644 --- a/src/Recyclarr.ServarrApi/Http/ServarrRequestBuilder.cs +++ b/src/Recyclarr.ServarrApi/Http/Servarr/ServarrRequestBuilder.cs @@ -7,12 +7,13 @@ using Recyclarr.Json; using Recyclarr.Settings; using Serilog; -namespace Recyclarr.ServarrApi.Http; +namespace Recyclarr.ServarrApi.Http.Servarr; public class ServarrRequestBuilder( ILogger log, IFlurlClientCache clientCache, - ISettingsProvider settingsProvider) + ISettingsProvider settingsProvider, + IEnumerable eventHandlers) : IServarrRequestBuilder { public IFlurlRequest Request(IServiceConfiguration config, params object[] path) @@ -30,10 +31,14 @@ public class ServarrRequestBuilder( [SuppressMessage("Security", "CA5359:Do Not Disable Certificate Validation")] private void Configure(IFlurlClientBuilder builder) { + foreach (var handler in eventHandlers.Select(x => (x.EventType, x))) + { + builder.EventHandlers.Add(handler); + } + builder.WithSettings(settings => { settings.JsonSerializer = new DefaultJsonSerializer(GlobalJsonSerializerSettings.Services); - FlurlLogging.SetupLogging(settings, log); }); builder.ConfigureInnerHandler(handler => diff --git a/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs b/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs index 8dd37dba..3da9f603 100644 --- a/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs +++ b/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs @@ -1,7 +1,7 @@ using Flurl.Http; using Recyclarr.Common; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; namespace Recyclarr.ServarrApi.MediaNaming; diff --git a/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs b/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs index 6c8d7a43..83c5ec96 100644 --- a/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs +++ b/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs @@ -1,6 +1,6 @@ using Flurl.Http; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; namespace Recyclarr.ServarrApi.QualityDefinition; diff --git a/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs b/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs index 40855558..d89ba3fe 100644 --- a/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs +++ b/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs @@ -1,6 +1,6 @@ using Flurl.Http; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; namespace Recyclarr.ServarrApi.QualityProfile; diff --git a/src/Recyclarr.ServarrApi/ReleaseProfile/ReleaseProfileApiService.cs b/src/Recyclarr.ServarrApi/ReleaseProfile/ReleaseProfileApiService.cs index da67445d..ebc468eb 100644 --- a/src/Recyclarr.ServarrApi/ReleaseProfile/ReleaseProfileApiService.cs +++ b/src/Recyclarr.ServarrApi/ReleaseProfile/ReleaseProfileApiService.cs @@ -1,6 +1,6 @@ using Flurl.Http; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; namespace Recyclarr.ServarrApi.ReleaseProfile; diff --git a/src/Recyclarr.ServarrApi/System/SystemApiService.cs b/src/Recyclarr.ServarrApi/System/SystemApiService.cs index 6968bc22..ad61cf33 100644 --- a/src/Recyclarr.ServarrApi/System/SystemApiService.cs +++ b/src/Recyclarr.ServarrApi/System/SystemApiService.cs @@ -1,6 +1,6 @@ using Flurl.Http; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; namespace Recyclarr.ServarrApi.System; diff --git a/src/Recyclarr.ServarrApi/Tag/SonarrTagApiService.cs b/src/Recyclarr.ServarrApi/Tag/SonarrTagApiService.cs index 4c5a299b..24a0090f 100644 --- a/src/Recyclarr.ServarrApi/Tag/SonarrTagApiService.cs +++ b/src/Recyclarr.ServarrApi/Tag/SonarrTagApiService.cs @@ -1,6 +1,6 @@ using Flurl.Http; using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.Http; +using Recyclarr.ServarrApi.Http.Servarr; namespace Recyclarr.ServarrApi.Tag;