refactor: Upgrade to Flurl 4.0-pre5

This required significant changes in how Flurl Client configuration and
creation takes place.
pull/231/head
Robert Dailey 1 year ago
parent 1db5aea11d
commit a8224d97d8

@ -11,7 +11,7 @@
<PackageVersion Include="CliWrap" Version="3.6.4" />
<PackageVersion Include="FluentValidation" Version="11.8.0" />
<PackageVersion Include="Flurl" Version="3.0.7" />
<PackageVersion Include="Flurl.Http" Version="4.0.0-pre3" />
<PackageVersion Include="Flurl.Http" Version="4.0.0-pre5" />
<PackageVersion Include="GitVersion.MsBuild" Version="5.12.0" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.2.0" />
<PackageVersion Include="JorgeSerrano.Json.JsonSnakeCaseNamingPolicy" Version="0.9.0" />

@ -1,16 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Flurl.Http.Configuration;
namespace Recyclarr.Common.Networking;
[SuppressMessage("SonarCloud", "S4830:Server certificates should be verified during SSL/TLS connections")]
public class UntrustedCertClientFactory : DefaultHttpClientFactory
{
public override HttpMessageHandler CreateMessageHandler()
{
return new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
}
}

@ -14,7 +14,14 @@ public class ApiServicesAutofacModule : Module
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<PerBaseUrlFlurlClientFactory>().As<IFlurlClientFactory>().SingleInstance();
builder.RegisterType<FlurlConfigurator>();
builder.Register(c =>
{
var config = c.Resolve<FlurlConfigurator>();
return new FlurlClientCache().ConfigureAll(x => config.Configure(x));
})
.As<IFlurlClientCache>()
.SingleInstance();
builder.RegisterType<SystemApiService>().As<ISystemApiService>();
builder.RegisterType<ServarrRequestBuilder>().As<IServarrRequestBuilder>();

@ -0,0 +1,46 @@
using System.Diagnostics.CodeAnalysis;
using System.Net.Security;
using Flurl.Http.Configuration;
using Recyclarr.Json;
using Recyclarr.Settings;
using Serilog;
namespace Recyclarr.ServarrApi.Http;
public class FlurlConfigurator
{
private readonly ILogger _log;
private readonly ISettingsProvider _settingsProvider;
public FlurlConfigurator(ILogger log, ISettingsProvider settingsProvider)
{
_log = log;
_settingsProvider = settingsProvider;
}
[SuppressMessage("SonarCloud", "S4830:Server certificates should be verified during SSL/TLS connections")]
[SuppressMessage("Security", "CA5359:Do Not Disable Certificate Validation")]
public void Configure(IFlurlClientBuilder builder)
{
builder.WithSettings(settings =>
{
settings.JsonSerializer = new DefaultJsonSerializer(GlobalJsonSerializerSettings.Services);
FlurlLogging.SetupLogging(settings, _log);
});
builder.ConfigureInnerHandler(handler =>
{
if (!_settingsProvider.Settings.EnableSslCertificateValidation)
{
_log.Warning(
"Security Risk: Certificate validation is being DISABLED because setting " +
"`enable_ssl_certificate_validation` is set to `false`");
handler.SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (_, _, _, _) => true
};
}
});
}
}

@ -1,53 +1,24 @@
using Flurl;
using Flurl.Http;
using Flurl.Http.Configuration;
using Recyclarr.Common.Networking;
using Recyclarr.Config.Models;
using Recyclarr.Json;
using Recyclarr.Settings;
using Serilog;
namespace Recyclarr.ServarrApi.Http;
public class ServarrRequestBuilder : IServarrRequestBuilder
{
private readonly ILogger _log;
private readonly ISettingsProvider _settingsProvider;
private readonly IFlurlClientFactory _clientFactory;
private readonly IFlurlClientCache _clientCache;
public ServarrRequestBuilder(ILogger log, ISettingsProvider settingsProvider, IFlurlClientFactory clientFactory)
public ServarrRequestBuilder(IFlurlClientCache clientCache)
{
_log = log;
_settingsProvider = settingsProvider;
_clientFactory = clientFactory;
_clientCache = clientCache;
}
public IFlurlRequest Request(IServiceConfiguration config, params object[] path)
{
var client = _clientFactory.Get(config.BaseUrl.AppendPathSegments("api", "v3"));
client.Settings = GetClientSettings();
var client = _clientCache.Get(config.InstanceName);
client.BaseUrl ??= config.BaseUrl.AppendPathSegments("api", "v3");
return client.Request(path)
.WithHeader("X-Api-Key", config.ApiKey);
}
private ClientFlurlHttpSettings GetClientSettings()
{
var settings = new ClientFlurlHttpSettings
{
JsonSerializer = new DefaultJsonSerializer(GlobalJsonSerializerSettings.Services)
};
FlurlLogging.SetupLogging(settings, _log);
// ReSharper disable once InvertIf
if (!_settingsProvider.Settings.EnableSslCertificateValidation)
{
_log.Warning(
"Security Risk: Certificate validation is being DISABLED because setting " +
"`enable_ssl_certificate_validation` is set to `false`");
settings.HttpClientFactory = new UntrustedCertClientFactory();
}
return settings;
}
}

@ -14,12 +14,13 @@ public class CustomFormatServiceTest : IntegrationTestFixture
{
var resourceData = new ResourceDataReader(typeof(CustomFormatServiceTest), "Data");
var jsonBody = resourceData.ReadData("issue_178.json");
var config = new RadarrConfiguration {InstanceName = "instance"};
using var http = new HttpTest();
http.RespondWith(jsonBody);
var sut = Resolve<CustomFormatApiService>();
var result = await sut.GetCustomFormats(Substitute.ForPartsOf<ServiceConfiguration>());
var result = await sut.GetCustomFormats(config);
result.Should().HaveCountGreaterThan(5);
}

Loading…
Cancel
Save