From 9c8c485c98a0978c01c512fcf406a8caa43f53c4 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Sat, 17 Aug 2013 17:17:37 -0700 Subject: [PATCH] added RestSharpExtensions to help validate REST response --- .../MetadataSourceTests/TraktProxyFixture.cs | 8 +++ NzbDrone.Core/MetadataSource/TraktProxy.cs | 22 ++---- .../Notifications/Pushover/Pushover.cs | 10 +-- .../Notifications/Pushover/PushoverService.cs | 23 ++---- NzbDrone.Core/NzbDrone.Core.csproj | 3 + NzbDrone.Core/Rest/RestException.cs | 26 +++++++ NzbDrone.Core/Rest/RestSharpExtensions.cs | 70 +++++++++++++++++++ NzbDrone.Test.Common/LoggingTest.cs | 2 +- NzbDrone.sln.DotSettings | 1 + 9 files changed, 126 insertions(+), 39 deletions(-) create mode 100644 NzbDrone.Core/Rest/RestException.cs create mode 100644 NzbDrone.Core/Rest/RestSharpExtensions.cs diff --git a/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs b/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs index fea1cfefd..52715f18c 100644 --- a/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs +++ b/NzbDrone.Core.Test/MetadataSourceTests/TraktProxyFixture.cs @@ -4,6 +4,7 @@ using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.MetadataSource; +using NzbDrone.Core.Rest; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; using NzbDrone.Test.Common.Categories; @@ -45,6 +46,13 @@ public void should_be_able_to_get_series_detail(int tvdbId) ValidateEpisodes(details.Item2); } + + [Test] + public void getting_details_of_invalid_series() + { + Assert.Throws(() => Subject.GetSeriesInfo(Int32.MaxValue)); + } + private void ValidateSeries(Series series) { series.Should().NotBeNull(); diff --git a/NzbDrone.Core/MetadataSource/TraktProxy.cs b/NzbDrone.Core/MetadataSource/TraktProxy.cs index 99bfd09da..6dca25834 100644 --- a/NzbDrone.Core/MetadataSource/TraktProxy.cs +++ b/NzbDrone.Core/MetadataSource/TraktProxy.cs @@ -10,6 +10,7 @@ using NzbDrone.Core.Tv; using RestSharp; using Episode = NzbDrone.Core.Tv.Episode; +using NzbDrone.Core.Rest; namespace NzbDrone.Core.MetadataSource { @@ -19,23 +20,20 @@ public List SearchForNewSeries(string title) { var client = BuildClient("search", "shows"); var restRequest = new RestRequest(title.ToSearchTerm()); - var response = client.Execute>(restRequest); + var response = client.ExecuteAndValidate>(restRequest); - CheckForError(response); - - return response.Data.Select(MapSeries).ToList(); + return response.Select(MapSeries).ToList(); } public Tuple> GetSeriesInfo(int tvDbSeriesId) { var client = BuildClient("show", "summary"); var restRequest = new RestRequest(tvDbSeriesId.ToString() + "/extended"); - var response = client.Execute(restRequest); + var response = client.ExecuteAndValidate(restRequest); - CheckForError(response); - var episodes = response.Data.seasons.SelectMany(c => c.episodes).Select(MapEpisode).ToList(); - var series = MapSeries(response.Data); + var episodes = response.seasons.SelectMany(c => c.episodes).Select(MapEpisode).ToList(); + var series = MapSeries(response); return new Tuple>(series, episodes); } @@ -126,12 +124,6 @@ private static string FromIsoToString(string iso) return match.Captures[0].Value; } - private void CheckForError(IRestResponse response) - { - if (response.StatusCode != HttpStatusCode.OK) - { - throw new TraktCommunicationException(response.ErrorMessage, response.ErrorException); - } - } + } } \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/Pushover/Pushover.cs b/NzbDrone.Core/Notifications/Pushover/Pushover.cs index c4ab7153a..b4a3e5a56 100644 --- a/NzbDrone.Core/Notifications/Pushover/Pushover.cs +++ b/NzbDrone.Core/Notifications/Pushover/Pushover.cs @@ -4,11 +4,11 @@ namespace NzbDrone.Core.Notifications.Pushover { public class Pushover : NotificationBase { - private readonly IPushoverService _pushoverService; + private readonly IPushoverProxy _pushoverProxy; - public Pushover(IPushoverService pushoverService) + public Pushover(IPushoverProxy pushoverProxy) { - _pushoverService = pushoverService; + _pushoverProxy = pushoverProxy; } public override string Name @@ -30,14 +30,14 @@ public override void OnGrab(string message) { const string title = "Episode Grabbed"; - _pushoverService.SendNotification(title, message, Settings.UserKey, (PushoverPriority)Settings.Priority); + _pushoverProxy.SendNotification(title, message, Settings.UserKey, (PushoverPriority)Settings.Priority); } public override void OnDownload(string message, Series series) { const string title = "Episode Downloaded"; - _pushoverService.SendNotification(title, message, Settings.UserKey, (PushoverPriority)Settings.Priority); + _pushoverProxy.SendNotification(title, message, Settings.UserKey, (PushoverPriority)Settings.Priority); } public override void AfterRename(Series series) diff --git a/NzbDrone.Core/Notifications/Pushover/PushoverService.cs b/NzbDrone.Core/Notifications/Pushover/PushoverService.cs index 2d8a7ed63..cab9639bb 100644 --- a/NzbDrone.Core/Notifications/Pushover/PushoverService.cs +++ b/NzbDrone.Core/Notifications/Pushover/PushoverService.cs @@ -1,27 +1,19 @@ -using System.Net; -using NLog; -using NzbDrone.Common.Messaging; +using NzbDrone.Common.Messaging; using RestSharp; +using NzbDrone.Core.Rest; namespace NzbDrone.Core.Notifications.Pushover { - public interface IPushoverService + public interface IPushoverProxy { void SendNotification(string title, string message, string userKey, PushoverPriority priority); } - public class PushoverService : IPushoverService, IExecute + public class PushoverProxy : IPushoverProxy, IExecute { - private readonly Logger _logger; - private const string TOKEN = "yz9b4U215iR4vrKFRfjNXP24NMNPKJ"; private const string URL = "https://api.pushover.net/1/messages.json"; - public PushoverService(Logger logger) - { - _logger = logger; - } - public void SendNotification(string title, string message, string userKey, PushoverPriority priority) { var client = new RestClient(URL); @@ -32,12 +24,7 @@ public void SendNotification(string title, string message, string userKey, Pusho request.AddParameter("message", message); request.AddParameter("priority", (int)priority); - var response = client.Execute(request); - - if (response.StatusCode != HttpStatusCode.OK) - { - throw new InvalidResponseException(response.Content); - } + client.ExecuteAndValidate(request); } public void Execute(TestPushoverCommand message) diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 992b5d008..67dfebd11 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -342,6 +342,8 @@ + + @@ -541,6 +543,7 @@ + diff --git a/NzbDrone.Core/Rest/RestException.cs b/NzbDrone.Core/Rest/RestException.cs new file mode 100644 index 000000000..207a20e75 --- /dev/null +++ b/NzbDrone.Core/Rest/RestException.cs @@ -0,0 +1,26 @@ +using System; +using RestSharp; + +namespace NzbDrone.Core.Rest +{ + public class RestException : Exception + { + public IRestResponse Response { get; private set; } + + public RestException(IRestResponse response, IRestClient restClient) + : base(string.Format("REST request failed: [{0}] [{1}] at [{2}]", (int)response.StatusCode, response.Request.Method, restClient.BuildUri(response.Request))) + { + Response = response; + } + + public override string ToString() + { + if (Response != null) + { + return base.ToString() + Environment.NewLine + Response.Content; + } + + return base.ToString(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Rest/RestSharpExtensions.cs b/NzbDrone.Core/Rest/RestSharpExtensions.cs new file mode 100644 index 000000000..b1a1ee968 --- /dev/null +++ b/NzbDrone.Core/Rest/RestSharpExtensions.cs @@ -0,0 +1,70 @@ +using System.Net; +using NLog; +using NzbDrone.Common.EnsureThat; +using NzbDrone.Common.Serializer; +using RestSharp; + +namespace NzbDrone.Core.Rest +{ + public static class RestSharpExtensions + { + private static readonly Logger Logger = LogManager.GetLogger("RestExtensions"); + + public static IRestResponse ValidateResponse(this IRestResponse response, IRestClient restClient) + { + Ensure.That(() => response).IsNotNull(); + + if (response.Request == null && response.ErrorException != null) + { + throw response.ErrorException; + } + + Ensure.That(() => response.Request).IsNotNull(); + Ensure.That(() => restClient).IsNotNull(); + + Logger.Debug("Validating Responses from [{0}] [{1}] status: [{2}] body:[{3}]", response.Request.Method, restClient.BuildUri(response.Request), response.StatusCode, response.Content); + + if (response.ResponseUri == null) + { + Logger.ErrorException("Error communicating with server", response.ErrorException); + throw response.ErrorException; + } + + switch (response.StatusCode) + { + case HttpStatusCode.OK: + { + return response; + } + default: + { + Logger.Warn("[{0}] [{1}] Failed. [{2}]", response.Request.Method, response.ResponseUri.ToString(), response.StatusCode); + throw new RestException(response, restClient); + } + } + } + + public static T Read(this IRestResponse restResponse, IRestClient restClient) where T : class, new() + { + restResponse.ValidateResponse(restClient); + + return Json.Deserialize(restResponse.Content); + } + + public static T ExecuteAndValidate(this IRestClient client, IRestRequest request) where T : class, new() + { + return client.Execute(request).Read(client); + } + + public static IRestResponse ExecuteAndValidate(this IRestClient client, IRestRequest request) + { + return client.Execute(request).ValidateResponse(client); + } + + + public static void AddQueryString(this IRestRequest request, string name, object value) + { + request.AddParameter(name, value.ToString(), ParameterType.GetOrPost); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Test.Common/LoggingTest.cs b/NzbDrone.Test.Common/LoggingTest.cs index 33668b2da..3970ec32d 100644 --- a/NzbDrone.Test.Common/LoggingTest.cs +++ b/NzbDrone.Test.Common/LoggingTest.cs @@ -48,7 +48,7 @@ public void LoggingDownBase() //can't use because of a bug in mono with 2.6.2, //https://bugs.launchpad.net/nunitv2/+bug/1076932 - //if (TestContext.CurrentContext.Result.State == TestState.Success) + if (OsInfo.IsWindows && TestContext.CurrentContext.Result.State == TestState.Success) { ExceptionVerification.AssertNoUnexcpectedLogs(); } diff --git a/NzbDrone.sln.DotSettings b/NzbDrone.sln.DotSettings index a17d31632..86121dceb 100644 --- a/NzbDrone.sln.DotSettings +++ b/NzbDrone.sln.DotSettings @@ -8,6 +8,7 @@ ERROR ERROR HINT + WARNING HINT <?xml version="1.0" encoding="utf-16"?><Profile name="NzbDrone"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>IMPLICIT_EXCEPT_SIMPLE_TYPES</LocalVariableStyle><ForeachVariableStyle>ALWAYS_IMPLICIT</ForeachVariableStyle></CSUseVar><CSUpdateFileHeader>True</CSUpdateFileHeader><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReorderTypeMembers>True</CSReorderTypeMembers><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags></Profile> NzbDrone