From 601f144afeca2fb47b88a41b39c777d4c9ca4fc0 Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Tue, 17 May 2022 17:03:57 -0500 Subject: [PATCH] fix: Cleanup and centralize URL sanitization There were some corner cases that were not handled (such as logging the instance URL being processed). Additionally, code was simplified greatly by centralizing the sanitization logic. --- .../Command/Services/RadarrService.cs | 3 ++- .../Command/Services/SonarrService.cs | 3 ++- src/Recyclarr/Program.cs | 1 - src/TrashLib/Config/Services/IServerInfo.cs | 4 +-- src/TrashLib/Config/Services/ServerInfo.cs | 12 +++------ src/TrashLib/Extensions/FlurlExtensions.cs | 25 ++----------------- src/TrashLib/Extensions/FlurlLogging.cs | 16 ++++++++++-- .../CustomFormat/Api/CustomFormatService.cs | 3 ++- .../CustomFormat/Api/QualityProfileService.cs | 3 ++- .../CustomFormat/CustomFormatUpdater.cs | 3 ++- .../Api/QualityDefinitionService.cs | 5 ++-- src/TrashLib/Sonarr/Api/SonarrApi.cs | 12 +++------ 12 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/Recyclarr/Command/Services/RadarrService.cs b/src/Recyclarr/Command/Services/RadarrService.cs index c9e189c6..b677246f 100644 --- a/src/Recyclarr/Command/Services/RadarrService.cs +++ b/src/Recyclarr/Command/Services/RadarrService.cs @@ -1,6 +1,7 @@ using Recyclarr.Command.Helpers; using Recyclarr.Config; using Serilog; +using TrashLib.Extensions; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat; using TrashLib.Radarr.QualityDefinition; @@ -32,7 +33,7 @@ public class RadarrService : ServiceBase { foreach (var config in _configLoader.LoadMany(cmd.Config, "radarr")) { - _log.Information("Processing server {Url}", config.BaseUrl); + _log.Information("Processing server {Url}", FlurlLogging.SanitizeUrl(config.BaseUrl)); if (config.QualityDefinition != null) { diff --git a/src/Recyclarr/Command/Services/SonarrService.cs b/src/Recyclarr/Command/Services/SonarrService.cs index 75b94802..37a981cd 100644 --- a/src/Recyclarr/Command/Services/SonarrService.cs +++ b/src/Recyclarr/Command/Services/SonarrService.cs @@ -2,6 +2,7 @@ using Recyclarr.Command.Helpers; using Recyclarr.Config; using Serilog; +using TrashLib.Extensions; using TrashLib.Sonarr; using TrashLib.Sonarr.Config; using TrashLib.Sonarr.QualityDefinition; @@ -58,7 +59,7 @@ public class SonarrService : ServiceBase foreach (var config in _configLoader.LoadMany(cmd.Config, "sonarr")) { - _log.Information("Processing server {Url}", config.BaseUrl); + _log.Information("Processing server {Url}", FlurlLogging.SanitizeUrl(config.BaseUrl)); if (config.ReleaseProfiles.Count > 0) { diff --git a/src/Recyclarr/Program.cs b/src/Recyclarr/Program.cs index ba7fb58d..67aeb4e8 100644 --- a/src/Recyclarr/Program.cs +++ b/src/Recyclarr/Program.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Text; using Autofac; using Autofac.Core; -using Autofac.Core.Activators.Reflection; using CliFx; using CliFx.Infrastructure; using Recyclarr.Command.Helpers; diff --git a/src/TrashLib/Config/Services/IServerInfo.cs b/src/TrashLib/Config/Services/IServerInfo.cs index d25552c7..dd1c4b8f 100644 --- a/src/TrashLib/Config/Services/IServerInfo.cs +++ b/src/TrashLib/Config/Services/IServerInfo.cs @@ -1,8 +1,8 @@ -using Flurl.Http; +using Flurl; namespace TrashLib.Config.Services; public interface IServerInfo { - IFlurlRequest BuildRequest(); + Url BuildRequest(); } diff --git a/src/TrashLib/Config/Services/ServerInfo.cs b/src/TrashLib/Config/Services/ServerInfo.cs index e002071b..67428e56 100644 --- a/src/TrashLib/Config/Services/ServerInfo.cs +++ b/src/TrashLib/Config/Services/ServerInfo.cs @@ -1,29 +1,23 @@ using Flurl; -using Flurl.Http; -using Serilog; -using TrashLib.Extensions; namespace TrashLib.Config.Services; internal class ServerInfo : IServerInfo { private readonly IConfigurationProvider _config; - private readonly ILogger _log; - public ServerInfo(IConfigurationProvider config, ILogger log) + public ServerInfo(IConfigurationProvider config) { _config = config; - _log = log; } - public IFlurlRequest BuildRequest() + public Url BuildRequest() { var apiKey = _config.ActiveConfiguration.ApiKey; var baseUrl = _config.ActiveConfiguration.BaseUrl; return baseUrl .AppendPathSegment("api/v3") - .SetQueryParams(new {apikey = apiKey}) - .SanitizedLogging(_log); + .SetQueryParams(new {apikey = apiKey}); } } diff --git a/src/TrashLib/Extensions/FlurlExtensions.cs b/src/TrashLib/Extensions/FlurlExtensions.cs index 33b19b86..6546c1bd 100644 --- a/src/TrashLib/Extensions/FlurlExtensions.cs +++ b/src/TrashLib/Extensions/FlurlExtensions.cs @@ -1,37 +1,16 @@ using System.Text.RegularExpressions; -using Flurl; using Flurl.Http; -using Serilog; namespace TrashLib.Extensions; public static class FlurlExtensions { - public static IFlurlRequest SanitizedLogging(this Url url, ILogger log) - => new FlurlRequest(url).SanitizedLogging(log); - - public static IFlurlRequest SanitizedLogging(this IFlurlRequest request, ILogger log) - { - return request.ConfigureRequest(settings => FlurlLogging.SetupLogging(settings, log, SanitizeUrl)); - } - public static string SanitizedExceptionMessage(this FlurlHttpException exception) { const string expression = @"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}(\:[0-9]+)?\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)"; - return Regex.Replace(exception.ToString(), expression, match => SanitizeUrl(match.Value).ToString()); - } - - private static Url SanitizeUrl(Url url) - { - // Replace hostname and API key for user privacy - url.Host = "hostname"; - if (url.QueryParams.Contains("apikey")) - { - url.QueryParams.AddOrReplace("apikey", "SNIP"); - } - - return url; + return Regex.Replace(exception.ToString(), expression, + match => FlurlLogging.SanitizeUrl(match.Value).ToString()); } } diff --git a/src/TrashLib/Extensions/FlurlLogging.cs b/src/TrashLib/Extensions/FlurlLogging.cs index cac1064d..1bd82d2c 100644 --- a/src/TrashLib/Extensions/FlurlLogging.cs +++ b/src/TrashLib/Extensions/FlurlLogging.cs @@ -8,7 +8,7 @@ public static class FlurlLogging { public static void SetupLogging(FlurlHttpSettings settings, ILogger log, Func? urlInterceptor = null) { - urlInterceptor ??= url => url; + urlInterceptor ??= SanitizeUrl; settings.BeforeCall = call => { @@ -26,9 +26,21 @@ public static class FlurlLogging settings.OnRedirect = call => { log.Warning("HTTP Redirect received; this indicates a problem with your URL and/or reverse proxy: {Url}", - call.Redirect.Url); + urlInterceptor(call.Redirect.Url)); call.Redirect.Follow = false; }; } + + public static Url SanitizeUrl(Url url) + { + // Replace hostname and API key for user privacy + url.Host = "hostname"; + if (url.QueryParams.Contains("apikey")) + { + url.QueryParams.AddOrReplace("apikey", "SNIP"); + } + + return url; + } } diff --git a/src/TrashLib/Radarr/CustomFormat/Api/CustomFormatService.cs b/src/TrashLib/Radarr/CustomFormat/Api/CustomFormatService.cs index 57534ba3..06c9a66a 100644 --- a/src/TrashLib/Radarr/CustomFormat/Api/CustomFormatService.cs +++ b/src/TrashLib/Radarr/CustomFormat/Api/CustomFormatService.cs @@ -1,3 +1,4 @@ +using Flurl; using Flurl.Http; using Newtonsoft.Json.Linq; using TrashLib.Config.Services; @@ -49,5 +50,5 @@ internal class CustomFormatService : ICustomFormatService .DeleteAsync(); } - private IFlurlRequest BuildRequest() => _serverInfo.BuildRequest(); + private Url BuildRequest() => _serverInfo.BuildRequest(); } diff --git a/src/TrashLib/Radarr/CustomFormat/Api/QualityProfileService.cs b/src/TrashLib/Radarr/CustomFormat/Api/QualityProfileService.cs index 74df5f41..e5bb7d1e 100644 --- a/src/TrashLib/Radarr/CustomFormat/Api/QualityProfileService.cs +++ b/src/TrashLib/Radarr/CustomFormat/Api/QualityProfileService.cs @@ -1,3 +1,4 @@ +using Flurl; using Flurl.Http; using Newtonsoft.Json.Linq; using TrashLib.Config.Services; @@ -28,5 +29,5 @@ internal class QualityProfileService : IQualityProfileService .ReceiveJson(); } - private IFlurlRequest BuildRequest() => _serverInfo.BuildRequest(); + private Url BuildRequest() => _serverInfo.BuildRequest(); } diff --git a/src/TrashLib/Radarr/CustomFormat/CustomFormatUpdater.cs b/src/TrashLib/Radarr/CustomFormat/CustomFormatUpdater.cs index ad1b8926..44c4070f 100644 --- a/src/TrashLib/Radarr/CustomFormat/CustomFormatUpdater.cs +++ b/src/TrashLib/Radarr/CustomFormat/CustomFormatUpdater.cs @@ -1,5 +1,6 @@ using Common.Extensions; using Serilog; +using TrashLib.Extensions; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat.Processors; using TrashLib.Radarr.CustomFormat.Processors.PersistenceSteps; @@ -182,7 +183,7 @@ internal class CustomFormatUpdater : ICustomFormatUpdater if (_guideProcessor.ConfigData.Count == 0) { Log.Error("Guide processing yielded no custom formats for configured instance host {BaseUrl}", - config.BaseUrl); + FlurlLogging.SanitizeUrl(config.BaseUrl)); return false; } diff --git a/src/TrashLib/Radarr/QualityDefinition/Api/QualityDefinitionService.cs b/src/TrashLib/Radarr/QualityDefinition/Api/QualityDefinitionService.cs index 22d622ce..eba6a2b5 100644 --- a/src/TrashLib/Radarr/QualityDefinition/Api/QualityDefinitionService.cs +++ b/src/TrashLib/Radarr/QualityDefinition/Api/QualityDefinitionService.cs @@ -1,4 +1,5 @@ -using Flurl.Http; +using Flurl; +using Flurl.Http; using TrashLib.Config.Services; using TrashLib.Radarr.QualityDefinition.Api.Objects; @@ -29,5 +30,5 @@ internal class QualityDefinitionService : IQualityDefinitionService .ReceiveJson>(); } - private IFlurlRequest BuildRequest() => _serverInfo.BuildRequest(); + private Url BuildRequest() => _serverInfo.BuildRequest(); } diff --git a/src/TrashLib/Sonarr/Api/SonarrApi.cs b/src/TrashLib/Sonarr/Api/SonarrApi.cs index c82cd050..91ecdc05 100644 --- a/src/TrashLib/Sonarr/Api/SonarrApi.cs +++ b/src/TrashLib/Sonarr/Api/SonarrApi.cs @@ -1,26 +1,22 @@ -using Flurl.Http; +using Flurl; +using Flurl.Http; using Newtonsoft.Json.Linq; -using Serilog; using TrashLib.Config.Services; -using TrashLib.Extensions; using TrashLib.Sonarr.Api.Objects; namespace TrashLib.Sonarr.Api; public class SonarrApi : ISonarrApi { - private readonly ILogger _log; private readonly ISonarrReleaseProfileCompatibilityHandler _profileHandler; private readonly IServerInfo _serverInfo; public SonarrApi( IServerInfo serverInfo, - ISonarrReleaseProfileCompatibilityHandler profileHandler, - ILogger log) + ISonarrReleaseProfileCompatibilityHandler profileHandler) { _serverInfo = serverInfo; _profileHandler = profileHandler; - _log = log; } public async Task> GetTags() @@ -91,5 +87,5 @@ public class SonarrApi : ISonarrApi .ReceiveJson>(); } - private IFlurlRequest BaseUrl() => _serverInfo.BuildRequest().SanitizedLogging(_log); + private Url BaseUrl() => _serverInfo.BuildRequest(); }