fix: Output more detail about HTTP 4xx "bad data" responses

pull/201/head
Robert Dailey 2 years ago
parent aa8140add4
commit 01fdc0639f

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Better error messages for manually-specified, non-existent config files. - Better error messages for manually-specified, non-existent config files.
- More detail in error messages when Radarr/Sonarr API calls respond with HTTP 400 "Bad Data".
### Fixed ### Fixed

@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
using System.IO.Abstractions; using System.IO.Abstractions;
using Flurl.Http; using Flurl.Http;
using Recyclarr.Cli.Console.Settings; using Recyclarr.Cli.Console.Settings;
using Recyclarr.Common.Extensions;
using Recyclarr.TrashLib.Compatibility; using Recyclarr.TrashLib.Compatibility;
using Recyclarr.TrashLib.Config; using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Parsing; using Recyclarr.TrashLib.Config.Parsing;
@ -69,7 +70,7 @@ public class SyncProcessor : ISyncProcessor
} }
catch (Exception e) catch (Exception e)
{ {
HandleException(e); await HandleException(e);
failureDetected = true; failureDetected = true;
} }
@ -102,7 +103,7 @@ public class SyncProcessor : ISyncProcessor
} }
catch (Exception e) catch (Exception e)
{ {
HandleException(e); await HandleException(e);
failureDetected = true; failureDetected = true;
} }
} }
@ -110,7 +111,7 @@ public class SyncProcessor : ISyncProcessor
return failureDetected; return failureDetected;
} }
private void HandleException(Exception e) private async Task HandleException(Exception e)
{ {
switch (e) switch (e)
{ {
@ -121,6 +122,11 @@ public class SyncProcessor : ISyncProcessor
case FlurlHttpException e2: case FlurlHttpException e2:
_log.Error("HTTP error: {Message}", e2.SanitizedExceptionMessage()); _log.Error("HTTP error: {Message}", e2.SanitizedExceptionMessage());
foreach (var error in await GetValidationErrorsAsync(e2))
{
_log.Error("Reason: {Error}", error);
}
break; break;
default: default:
@ -128,15 +134,32 @@ public class SyncProcessor : ISyncProcessor
} }
} }
private static async Task<IReadOnlyCollection<string>> GetValidationErrorsAsync(FlurlHttpException e)
{
var response = await e.GetResponseJsonAsync<List<dynamic>>();
if (response is null)
{
return Array.Empty<string>();
}
return response
.Select(x => (string)x.errorMessage)
.NotNull(x => !string.IsNullOrEmpty(x))
.ToList();
}
private void PrintProcessingHeader(SupportedServices serviceType, IServiceConfiguration config) private void PrintProcessingHeader(SupportedServices serviceType, IServiceConfiguration config)
{ {
var instanceName = config.InstanceName; var instanceName = config.InstanceName;
_console.WriteLine($@" _console.WriteLine(
=========================================== $"""
Processing {serviceType} Server: [{instanceName}]
=========================================== ===========================================
"); Processing {serviceType} Server: [{instanceName}]
===========================================
""");
_log.Debug("Processing {Server} server {Name}", serviceType, instanceName); _log.Debug("Processing {Server} server {Name}", serviceType, instanceName);
} }

@ -52,6 +52,12 @@ public static class CollectionExtensions
return source.Where(x => x is not null).Select(x => x!); return source.Where(x => x is not null).Select(x => x!);
} }
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> source, Func<T, bool> predicate)
where T : class
{
return source.Where(x => x is not null && predicate(x)).Select(x => x!);
}
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> source) public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> source)
where T : struct where T : struct
{ {

Loading…
Cancel
Save