diff --git a/src/NzbDrone.Common/Http/TooManyRequestsException.cs b/src/NzbDrone.Common/Http/TooManyRequestsException.cs index 1c16f0b71..d1ea9b5ee 100644 --- a/src/NzbDrone.Common/Http/TooManyRequestsException.cs +++ b/src/NzbDrone.Common/Http/TooManyRequestsException.cs @@ -14,7 +14,18 @@ namespace NzbDrone.Common.Http { if (response.Headers.ContainsKey("Retry-After")) { - RetryAfter = TimeSpan.FromSeconds(int.Parse(response.Headers["Retry-After"].ToString())); + var retryAfter = response.Headers["Retry-After"].ToString(); + int seconds; + DateTime date; + + if (int.TryParse(retryAfter, out seconds)) + { + RetryAfter = TimeSpan.FromSeconds(seconds); + } + else if (DateTime.TryParse(retryAfter, out date)) + { + RetryAfter = date.ToUniversalTime() - DateTime.UtcNow; + } } } } diff --git a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs index 5c624b34b..9ba3756cf 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs @@ -143,7 +143,28 @@ namespace NzbDrone.Core.Test.Download Assert.Throws(() => Subject.DownloadReport(_parseResult)); Mocker.GetMock() - .Verify(v => v.RecordFailure(It.IsAny(), TimeSpan.FromMinutes(5)), Times.Once()); + .Verify(v => v.RecordFailure(It.IsAny(), TimeSpan.FromMinutes(5.0)), Times.Once()); + } + + [Test] + public void Download_report_should_trigger_indexer_backoff_on_http429_based_on_date() + { + var request = new HttpRequest("http://my.indexer.com"); + var response = new HttpResponse(request, new HttpHeader(), new byte[0], (HttpStatusCode)429); + response.Headers["Retry-After"] = DateTime.UtcNow.AddSeconds(300).ToString("r"); + + var mock = WithUsenetClient(); + mock.Setup(s => s.Download(It.IsAny())) + .Callback(v => + { + throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response)); + }); + + Assert.Throws(() => Subject.DownloadReport(_parseResult)); + + Mocker.GetMock() + .Verify(v => v.RecordFailure(It.IsAny(), + It.IsInRange(TimeSpan.FromMinutes(4.9), TimeSpan.FromMinutes(5.1), Range.Inclusive)), Times.Once()); } [Test]