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.
pull/76/head
Robert Dailey 3 years ago
parent 243d076087
commit 601f144afe

@ -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<IRadarrCommand>
{
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)
{

@ -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<ISonarrCommand>
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)
{

@ -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;

@ -1,8 +1,8 @@
using Flurl.Http;
using Flurl;
namespace TrashLib.Config.Services;
public interface IServerInfo
{
IFlurlRequest BuildRequest();
Url BuildRequest();
}

@ -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});
}
}

@ -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());
}
}

@ -8,7 +8,7 @@ public static class FlurlLogging
{
public static void SetupLogging(FlurlHttpSettings settings, ILogger log, Func<Url, Url>? 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;
}
}

@ -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();
}

@ -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<JObject>();
}
private IFlurlRequest BuildRequest() => _serverInfo.BuildRequest();
private Url BuildRequest() => _serverInfo.BuildRequest();
}

@ -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;
}

@ -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<List<RadarrQualityDefinitionItem>>();
}
private IFlurlRequest BuildRequest() => _serverInfo.BuildRequest();
private Url BuildRequest() => _serverInfo.BuildRequest();
}

@ -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<IList<SonarrTag>> GetTags()
@ -91,5 +87,5 @@ public class SonarrApi : ISonarrApi
.ReceiveJson<List<SonarrQualityDefinitionItem>>();
}
private IFlurlRequest BaseUrl() => _serverInfo.BuildRequest().SanitizedLogging(_log);
private Url BaseUrl() => _serverInfo.BuildRequest();
}

Loading…
Cancel
Save