Beispiel #1
0
        private void CheckInvalidParse(string input)
        {
            Assert.Throws <FormatException>(() => { RetryConditionHeaderValue.Parse(input); });

            Assert.False(RetryConditionHeaderValue.TryParse(input, out RetryConditionHeaderValue result));
            Assert.Null(result);
        }
        private static RetryParams ComputeAdalRetry(Exception ex)
        {
            if (ex is AdalServiceException)
            {
                AdalServiceException adalServiceException = (AdalServiceException)ex;

                // When the Service Token Server (STS) is too busy because of “too many requests”,
                // it returns an HTTP error 429 with a hint about when you can try again (Retry-After response field) as a delay in seconds
                if (adalServiceException.ErrorCode == MsalTemporarilyUnavailable || adalServiceException.StatusCode == HttpTooManyRequests)
                {
                    RetryConditionHeaderValue retryAfter = adalServiceException.Headers.RetryAfter;

                    // Depending on the service, the recommended retry time may be in retryAfter.Delta or retryAfter.Date. Check both.
                    if (retryAfter != null && retryAfter.Delta.HasValue)
                    {
                        return(new RetryParams(retryAfter.Delta.Value));
                    }
                    else if (retryAfter != null && retryAfter.Date.HasValue)
                    {
                        return(new RetryParams(retryAfter.Date.Value.Offset));
                    }

                    // We got a 429 but didn't get a specific back-off time. Use the default
                    return(RetryParams.DefaultBackOff(0));
                }
            }

            return(RetryParams.DefaultBackOff(0));
        }
        public void Parse()
        {
            var res = RetryConditionHeaderValue.Parse("44");

            Assert.IsNull(res.Date, "#1");
            Assert.AreEqual(new TimeSpan(0, 0, 44), res.Delta, "#2");
        }
Beispiel #4
0
        public async Task WaitAsync()
        {
            while (true)
            {
                try
                {
                    await JobApi.WaitAsync(CorrelationId);

                    Console.WriteLine("Job's done!");
                    return;
                }
                catch (HttpOperationException ex) when((int)ex.Response.StatusCode >= 500)
                {
                    string retryAfterStr = ex.Response.Headers["Retry-After"].FirstOrDefault();
                    RetryConditionHeaderValue retryAfter =
                        retryAfterStr == null ? null : RetryConditionHeaderValue.Parse(retryAfterStr);
                    TimeSpan retryTimeSpan = retryAfter?.Delta ?? TimeSpan.FromMinutes(1);
                    await Task.Delay(retryTimeSpan);
                }
                catch (TaskCanceledException)
                {
                    await Task.Delay(TimeSpan.FromMinutes(1));
                }
            }
        }
        private void CheckInvalidTryParse(string input)
        {
            RetryConditionHeaderValue result = null;

            Assert.False(RetryConditionHeaderValue.TryParse(input, out result));
            Assert.Null(result);
        }
        public void TryParse_Invalid()
        {
            RetryConditionHeaderValue res;

            Assert.IsFalse(RetryConditionHeaderValue.TryParse("", out res), "#1");
            Assert.IsNull(res, "#2");
        }
Beispiel #7
0
        public async Task <HttpResponseMessage> AuthenticateEnterpriseUser(EnterpriseUserCredentials credentials)
        {
            HttpResponseMessage result = new HttpResponseMessage();

            if (credentials.UserName == "Test" && credentials.Password == "Testesen")
            {
                result.StatusCode = HttpStatusCode.TooManyRequests;
                RetryConditionHeaderValue retryAfter = new RetryConditionHeaderValue(DateTime.Now);
                result.Headers.RetryAfter = retryAfter;
            }
            else if (credentials.UserName == "ValidUser" && credentials.Password == "ValidPassword")
            {
                result.StatusCode = HttpStatusCode.OK;
                result.Content    = GetEnterpriseUserContent(credentials.UserName);
            }
            else if (credentials.UserName == "ValidUser2" && credentials.Password == "Valid:Password")
            {
                result.StatusCode = HttpStatusCode.OK;
                result.Content    = GetEnterpriseUserContent(credentials.UserName);
            }
            else
            {
                result.StatusCode = HttpStatusCode.NotFound;
            }

            return(await Task.FromResult(result));
        }
        private static void CheckInvalidGetRetryConditionLength(string input, int startIndex)
        {
            object result = null;

            Assert.Equal(0, RetryConditionHeaderValue.GetRetryConditionLength(input, startIndex, out result));
            Assert.Null(result);
        }
Beispiel #9
0
        public async Task RetryAfterTimestamp()
        {
            var clock     = new MockClock();
            var timestamp = clock.UtcNow.AddSeconds(4).ToString("r");
            var handler   = new MockMessageHandler()
            {
                StatusCode   = HttpStatusCode.ServiceUnavailable,
                ApplyHeaders = (headers, contentHeaders) =>
                {
                    headers.RetryAfter = RetryConditionHeaderValue.Parse(timestamp);
                },
                Response = "{}",
            };
            var waiter     = new MockWaiter();
            var httpClient = CreateHttpClient(handler, RetryOptions.Default, waiter, clock);

            var response = await httpClient.SendAsync(CreateRequest());

            Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
            Assert.Equal(5, handler.Calls);
            Assert.Equal(4, waiter.WaitTimes.Count);
            foreach (var timespan in waiter.WaitTimes)
            {
                // Due to the date format used in HTTP headers, the milliseconds precision gets
                // lost. Therefore the actual delay is going to be a value between 3 and 4 seconds.
                Assert.True(timespan.TotalSeconds > 3.0 && timespan.TotalSeconds <= 4.0);
            }
        }
        private async Task <bool> WaitIfNotTooLong(RetryConditionHeaderValue retryAfter)
        {
            var timeToWait = _MaxPerRequestWaitTime;

            if (retryAfter != null)
            {
                if (retryAfter.Date != null)
                {
                    timeToWait = retryAfter.Date.Value.ToLocalTime().Subtract(DateTime.Now);
                }
                else if (retryAfter.Delta != null)
                {
                    timeToWait = retryAfter.Delta.Value;
                }
            }

            if (timeToWait.TotalMilliseconds > 0 && (timeToWait <= _MaxPerRequestWaitTime || _MaxPerRequestWaitTime == TimeSpan.Zero))
            {
#if SUPPORTS_TASKEX
                await TaskEx.Delay(timeToWait).ConfigureAwait(false);
#else
                await Task.Delay(timeToWait).ConfigureAwait(false);
#endif
                return(true);
            }

            return(false);
        }
        private void CheckValidTryParse(string input, RetryConditionHeaderValue expectedResult)
        {
            RetryConditionHeaderValue result = null;

            Assert.True(RetryConditionHeaderValue.TryParse(input, out result));
            Assert.Equal(expectedResult, result);
        }
Beispiel #12
0
        public async Task RetryAfterSeconds()
        {
            var handler = new MockMessageHandler()
            {
                StatusCode   = HttpStatusCode.ServiceUnavailable,
                ApplyHeaders = (headers, contentHeaders) =>
                {
                    headers.RetryAfter = RetryConditionHeaderValue.Parse("3");
                },
                Response = "{}",
            };
            var waiter     = new MockWaiter();
            var httpClient = CreateHttpClient(handler, RetryOptions.Default, waiter);

            var response = await httpClient.SendAsync(CreateRequest());

            Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
            Assert.Equal(5, handler.Calls);
            var expected = new List <TimeSpan>()
            {
                TimeSpan.FromSeconds(3),
                TimeSpan.FromSeconds(3),
                TimeSpan.FromSeconds(3),
                TimeSpan.FromSeconds(3),
            };

            Assert.Equal(expected, waiter.WaitTimes);
        }
Beispiel #13
0
        public void Ctor_DateOverload_MatchExpectation()
        {
            RetryConditionHeaderValue retryCondition = new RetryConditionHeaderValue(
                new DateTimeOffset(2010, 7, 15, 12, 33, 57, TimeSpan.Zero));

            Assert.Null(retryCondition.Delta);
            Assert.Equal(new DateTimeOffset(2010, 7, 15, 12, 33, 57, TimeSpan.Zero), retryCondition.Date);
        }
Beispiel #14
0
        public void TryParse()
        {
            RetryConditionHeaderValue res;

            Assert.IsTrue(RetryConditionHeaderValue.TryParse("124", out res), "#1");
            Assert.IsNull(res.Date, "#2");
            Assert.AreEqual(new TimeSpan(0, 2, 4), res.Delta, "#3");
        }
Beispiel #15
0
        public void Ctor_EntityTagOverload_MatchExpectation()
        {
            RetryConditionHeaderValue retryCondition = new RetryConditionHeaderValue(new TimeSpan(0, 0, 3));

            Assert.Equal(new TimeSpan(0, 0, 3), retryCondition.Delta);
            Assert.Null(retryCondition.Date);

            Assert.Throws <ArgumentOutOfRangeException>(() => { new RetryConditionHeaderValue(new TimeSpan(1234567, 0, 0)); });
        }
Beispiel #16
0
        private static void CallGetRetryConditionLength(string input, int startIndex, int expectedLength,
                                                        out RetryConditionHeaderValue result)
        {
            object temp = null;

            Assert.Equal(expectedLength, RetryConditionHeaderValue.GetRetryConditionLength(input, startIndex,
                                                                                           out temp));
            result = temp as RetryConditionHeaderValue;
        }
Beispiel #17
0
        public void ToString_UseDifferentRetryConditions_AllSerializedCorrectly()
        {
            RetryConditionHeaderValue retryCondition = new RetryConditionHeaderValue(new TimeSpan(0, 0, 50000000));

            Assert.Equal("50000000", retryCondition.ToString());

            retryCondition = new RetryConditionHeaderValue(new DateTimeOffset(2010, 7, 15, 12, 33, 57, TimeSpan.Zero));
            Assert.Equal("Thu, 15 Jul 2010 12:33:57 GMT", retryCondition.ToString());
        }
        private static TimeSpan GetServerWaitDuration(RetryConditionHeaderValue retryAfter)
        {
            if (retryAfter == null)
            {
                return(TimeSpan.Zero);
            }

            return(retryAfter.Date.HasValue
                ? retryAfter.Date.Value - DateTime.UtcNow
                : retryAfter.Delta.GetValueOrDefault(TimeSpan.Zero));
        }
Beispiel #19
0
        public void Equals()
        {
            var value = new RetryConditionHeaderValue(new DateTimeOffset(DateTime.Today));

            Assert.AreEqual(value, new RetryConditionHeaderValue(new DateTimeOffset(DateTime.Today)), "#1");
            Assert.AreNotEqual(value, new RetryConditionHeaderValue(new DateTimeOffset()), "#2");

            value = new RetryConditionHeaderValue(new TimeSpan(300));
            Assert.AreEqual(value, new RetryConditionHeaderValue(new TimeSpan(300)), "#4");
            Assert.AreNotEqual(value, new RetryConditionHeaderValue(new TimeSpan(44)), "#5");
        }
        private void CheckValidParsedValue(string input, int startIndex, RetryConditionHeaderValue expectedResult,
                                           int expectedIndex)
        {
            HttpHeaderParser parser = GenericHeaderParser.RetryConditionParser;
            object           result = null;

            Assert.True(parser.TryParseValue(input, null, ref startIndex, out result),
                        string.Format("TryParse returned false. Input: '{0}'", input));
            Assert.Equal(expectedIndex, startIndex);
            Assert.Equal(expectedResult, result);
        }
Beispiel #21
0
        public void Properties()
        {
            var value = new RetryConditionHeaderValue(new TimeSpan(5000));

            Assert.IsNull(value.Date, "#1");
            Assert.AreEqual(new TimeSpan(5000), value.Delta, "#2");

            value = new RetryConditionHeaderValue(new DateTimeOffset(DateTime.Today));
            Assert.AreEqual(new DateTimeOffset(DateTime.Today), value.Date, "#3");
            Assert.IsNull(value.Delta, "#4");
        }
Beispiel #22
0
        public async Task <HttpResponseMessage> AuthenticateEnterpriseUser(EnterpriseUserCredentials credentials)
        {
            if (credentials.UserName == "Test" && credentials.Password == "Testesen")
            {
                string credentialsJson = JsonSerializer.Serialize(credentials);
                var    request         = new HttpRequestMessage
                {
                    Method     = HttpMethod.Post,
                    RequestUri = new Uri(_settings.BridgeAuthnApiEndpoint + "enterpriseuser"),
                    Content    = new StringContent(credentialsJson.ToString(), Encoding.UTF8, "application/json")
                };

                var result = await _client.SendAsync(request).ConfigureAwait(false);

                result.StatusCode = HttpStatusCode.TooManyRequests;
                RetryConditionHeaderValue retryAfter = new RetryConditionHeaderValue(DateTime.Now);
                result.Headers.RetryAfter = retryAfter;
                return(result);
            }
            else if (credentials.UserName == "ValidUser" && credentials.Password == "ValidPassword")
            {
                string credentialsJson = JsonSerializer.Serialize(credentials);
                var    request         = new HttpRequestMessage
                {
                    Method     = HttpMethod.Post,
                    RequestUri = new Uri(_settings.BridgeAuthnApiEndpoint + "enterpriseuser"),
                    Content    = new StringContent(credentialsJson.ToString(), Encoding.UTF8, "application/json")
                };

                var result = await _client.SendAsync(request).ConfigureAwait(false);

                result.StatusCode = HttpStatusCode.OK;
                result.Content    = GetEnterpriseUserContent();

                return(result);
            }
            else
            {
                string credentialsJson = JsonSerializer.Serialize(credentials);
                var    request         = new HttpRequestMessage
                {
                    Method     = HttpMethod.Post,
                    RequestUri = new Uri(_settings.BridgeAuthnApiEndpoint + "enterpriseuser"),
                    Content    = new StringContent(credentialsJson.ToString(), Encoding.UTF8, "application/json")
                };

                var result = await _client.SendAsync(request).ConfigureAwait(false);

                result.StatusCode = HttpStatusCode.NotFound;
                return(result);
            }
        }
Beispiel #23
0
        public void Parse()
        {
            var res = RetryConditionHeaderValue.Parse("144");

            Assert.IsNull(res.Date, "#1");
            Assert.AreEqual(new TimeSpan(0, 0, 144), res.Delta, "#2");
            Assert.AreEqual("144", res.ToString(), "#3");

            res = RetryConditionHeaderValue.Parse("Fri, 31 Dec 1999 23:59:59 GMT");
            Assert.AreEqual(new DateTimeOffset(1999, 12, 31, 23, 59, 59, 0, TimeSpan.Zero), res.Date, "#11");
            Assert.IsNull(res.Delta, "#12");
            Assert.AreEqual("Fri, 31 Dec 1999 23:59:59 GMT", res.ToString(), "#13");
        }
Beispiel #24
0
        private async Task <HttpResponseMessage> SendInternal(HttpMethod method, CancellationToken cancellationToken)
        {
            // Account for the following settings:
            // - MaxRetryCount                          Max times to retry

            int timesToTry = _client.MaxRetryCount + 1;
            RetryConditionHeaderValue retryHeader = null;

            Debug.Assert(timesToTry >= 1);

            do
            {
                using (HttpRequestMessage req = PrepRequest(method))
                {
                    HttpResponseMessage resp =
                        await _client.HttpClient.SendAsync(req, cancellationToken).ConfigureAwait(false);

                    if (resp.StatusCode == (HttpStatusCode)429)
                    {
                        // The previous result was a ratelimit, read the Retry-After header and wait the allotted time
                        retryHeader = resp.Headers.RetryAfter;
                        TimeSpan?retryAfter = retryHeader?.Delta.Value;

                        if (retryAfter.HasValue && retryAfter.Value.TotalSeconds > 0)
                        {
                            await Task.Delay(retryAfter.Value, cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            // TMDb sometimes gives us 0-second waits, which can lead to rapid succession of requests
                            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
                        }

                        continue;
                    }

                    if (resp.IsSuccessStatusCode)
                    {
                        return(resp);
                    }

                    if (!resp.IsSuccessStatusCode)
                    {
                        return(resp);
                    }
                }
            } while (timesToTry-- > 0);

            // We never reached a success
            throw new RequestLimitExceededException(retryHeader?.Date, retryHeader?.Delta);
        }
Beispiel #25
0
        public void Clone_Call_CloneFieldsMatchSourceFields()
        {
            RetryConditionHeaderValue source = new RetryConditionHeaderValue(new TimeSpan(0, 0, 123456789));
            RetryConditionHeaderValue clone  = (RetryConditionHeaderValue)((ICloneable)source).Clone();

            Assert.Equal(source.Delta, clone.Delta);
            Assert.Null(clone.Date);

            source = new RetryConditionHeaderValue(new DateTimeOffset(2010, 7, 15, 12, 33, 57, TimeSpan.Zero));
            clone  = (RetryConditionHeaderValue)((ICloneable)source).Clone();

            Assert.Null(clone.Delta);
            Assert.Equal(source.Date, clone.Date);
        }
Beispiel #26
0
        private static Task HandleThrottling(RetryConditionHeaderValue wait)
        {
            TimeSpan waitFor = TimeSpan.FromSeconds(120);

            if (wait.Delta.HasValue)
            {
                waitFor = wait.Delta.Value;
            }
            if (wait.Date.HasValue)
            {
                waitFor = wait.Date.Value - DateTimeOffset.UtcNow;
            }
            return(Task.Delay(waitFor));
        }
Beispiel #27
0
        public void RetryAfter_ReadAndWriteProperty_CallsForwardedToHttpGeneralHeaders()
        {
            Assert.Null(headers.RetryAfter);

            RetryConditionHeaderValue retry = new RetryConditionHeaderValue(new TimeSpan(0, 1, 10));

            headers.RetryAfter = retry;
            Assert.Same(retry, headers.RetryAfter);

            headers.RetryAfter = null;
            Assert.Null(headers.RetryAfter);
            Assert.False(headers.Contains("RetryAfter"),
                         "Header store should not contain a header 'ETag' after setting it to null.");
        }
        private void OnComplete_(HttpResponseMessage response)
        {
            Uri location = response.Headers.Location;
            RetryConditionHeaderValue secondsToWait = response.Headers.RetryAfter;

            try
            {
                HttpStatusCode status = response.StatusCode;
                if (status == HttpStatusCode.Created)
                {
                    logger_?.Verbose("exit (CREATED)");
                    restClient_.SendAsyncRequest(listener_, location, "DELETE");
                    return;
                }

                if (status != HttpStatusCode.OK)
                {
                    listener_.OnFail(new EyesException($"Got bad status code when polling from the server. Status code: {status}"));
                    return;
                }
            }
            finally
            {
                response.Dispose();
            }

            if (location != null)
            {
                pollingUrl_ = location;
            }

            int timeToWait = sleepDuration_;

            if (secondsToWait != null)
            {
                timeToWait = (int)secondsToWait.Delta.Value.TotalMilliseconds;
            }
            else if (requestCount_++ >= 5)
            {
                sleepDuration_ *= 2;
                requestCount_   = 0;
                sleepDuration_  = Math.Min(5000, sleepDuration_);
            }

            Thread.Sleep(timeToWait);
            logger_?.Verbose("polling...");
            restClient_.SendAsyncRequest(this, pollingUrl_, "GET");
        }
Beispiel #29
0
        public void GetHashCode_UseSameAndDifferentRetryConditions_SameOrDifferentHashCodes()
        {
            RetryConditionHeaderValue retryCondition1 = new RetryConditionHeaderValue(new TimeSpan(0, 0, 1000000));
            RetryConditionHeaderValue retryCondition2 = new RetryConditionHeaderValue(new TimeSpan(0, 0, 1000000));
            RetryConditionHeaderValue retryCondition3 = new RetryConditionHeaderValue(
                new DateTimeOffset(2010, 7, 15, 12, 33, 57, TimeSpan.Zero));
            RetryConditionHeaderValue retryCondition4 = new RetryConditionHeaderValue(
                new DateTimeOffset(2008, 8, 16, 13, 44, 10, TimeSpan.Zero));
            RetryConditionHeaderValue retryCondition5 = new RetryConditionHeaderValue(
                new DateTimeOffset(2010, 7, 15, 12, 33, 57, TimeSpan.Zero));
            RetryConditionHeaderValue retryCondition6 = new RetryConditionHeaderValue(new TimeSpan(0, 0, 2000000));

            Assert.Equal(retryCondition1.GetHashCode(), retryCondition2.GetHashCode());
            Assert.NotEqual(retryCondition1.GetHashCode(), retryCondition3.GetHashCode());
            Assert.NotEqual(retryCondition3.GetHashCode(), retryCondition4.GetHashCode());
            Assert.Equal(retryCondition3.GetHashCode(), retryCondition5.GetHashCode());
            Assert.NotEqual(retryCondition1.GetHashCode(), retryCondition6.GetHashCode());
        }
Beispiel #30
0
        public async Task RetryAfterTooLarge()
        {
            var handler = new MockMessageHandler()
            {
                StatusCode   = HttpStatusCode.ServiceUnavailable,
                ApplyHeaders = (headers, contentHeaders) =>
                {
                    headers.RetryAfter = RetryConditionHeaderValue.Parse("300");
                },
                Response = "{}",
            };
            var waiter     = new MockWaiter();
            var httpClient = CreateHttpClient(handler, RetryOptions.Default, waiter);

            var response = await httpClient.SendAsync(CreateRequest());

            Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
            Assert.Equal(1, handler.Calls);
        }
		public static bool TryParse (string input, out RetryConditionHeaderValue parsedValue)
		{
			throw new NotImplementedException ();
		}