예제 #1
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);
            }
        }
예제 #2
0
        private void CheckInvalidParse(string input)
        {
            Assert.Throws <FormatException>(() => { RetryConditionHeaderValue.Parse(input); });

            Assert.False(RetryConditionHeaderValue.TryParse(input, out RetryConditionHeaderValue result));
            Assert.Null(result);
        }
예제 #3
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);
        }
예제 #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));
                }
            }
        }
        public void Parse()
        {
            var res = RetryConditionHeaderValue.Parse("44");

            Assert.IsNull(res.Date, "#1");
            Assert.AreEqual(new TimeSpan(0, 0, 44), res.Delta, "#2");
        }
예제 #6
0
        private void CheckValidParse(string input, RetryConditionHeaderValue expectedResult)
        {
            RetryConditionHeaderValue result = RetryConditionHeaderValue.Parse(input);

            Assert.Equal(expectedResult, result);

            Assert.True(RetryConditionHeaderValue.TryParse(input, out result));
            Assert.Equal(expectedResult, result);
        }
예제 #7
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");
        }
예제 #8
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);
        }
예제 #9
0
        public void Parse_Invalid()
        {
            try {
                RetryConditionHeaderValue.Parse(null);
                Assert.Fail("#1");
            } catch (FormatException) {
            }

            try {
                RetryConditionHeaderValue.Parse("  ");
                Assert.Fail("#2");
            } catch (FormatException) {
            }

            try {
                RetryConditionHeaderValue.Parse("a");
                Assert.Fail("#3");
            } catch (FormatException) {
            }
        }
        /// <summary>
        /// Insert a response HTTP header
        /// </summary>
        /// <param name="header">A <see cref="System.Net.Http.Headers.HttpResponseHeaders"/> object on wich the response header will be recorded.</param>
        /// <param name="name">The header attribute name.</param>
        /// <param name="value">The header attribute value.</param>
        public void AddResponseHeader(HttpResponseHeaders header, string name, string value)
        {
            if (name.Equals("Age", StringComparison.OrdinalIgnoreCase))
            {
                header.Age = TimeSpan.Parse(value);
            }

            else if (name.Equals("Cache-Control", StringComparison.OrdinalIgnoreCase))
            {
                header.CacheControl = CacheControlHeaderValue.Parse(value);
            }

            else if (name.Equals("Date", StringComparison.OrdinalIgnoreCase))
            {
                header.Date = DateTimeOffset.Parse(value);
            }

            else if (name.Equals("ETag", StringComparison.OrdinalIgnoreCase))
            {
                header.ETag = EntityTagHeaderValue.Parse(value);
            }

            else if (name.Equals("Location", StringComparison.OrdinalIgnoreCase))
            {
                header.Location = new Uri(value);
            }

            else if (name.Equals("Retry-After", StringComparison.OrdinalIgnoreCase))
            {
                header.RetryAfter = RetryConditionHeaderValue.Parse(value);
            }

            else
            {
                header.Add(name, value);
            }
        }
예제 #11
0
 private void CheckInvalidParse(string input)
 {
     Assert.Throws <FormatException>(() => { RetryConditionHeaderValue.Parse(input); });
 }
                    protected override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                                            CancellationToken cancellationToken)
                    {
                        TaskCompletionSource <HttpResponseMessage> tcs = new TaskCompletionSource <HttpResponseMessage>();
                        HttpResponseMessage response = new HttpResponseMessage();

                        response.RequestMessage = request;
                        tcs.SetResult(response);

                        Uri uri = request.RequestUri;

                        if (request.Method == HttpMethod.Post &&
                            uri.PathAndQuery.StartsWith("/api/sessions/running", StringComparison.OrdinalIgnoreCase))
                        {
                            response.StatusCode       = HttpStatusCode.Accepted;
                            expectedPollUrlPath_      = "/" + BASE_LOCATION + "status";
                            response.Headers.Location = new Uri(CommonData.DefaultServerUrl + BASE_LOCATION + "status");
                        }
                        else if (request.Method == HttpMethod.Get &&
                                 uri.PathAndQuery.StartsWith(expectedPollUrlPath_, StringComparison.OrdinalIgnoreCase))
                        {
                            if (iterations_ == 0 && counter_ == 0)
                            {
                                response.StatusCode = HttpStatusCode.OK;
                            }
                            else if (iterations_ > 0 && counter_ < iterations_)
                            {
                                response.StatusCode = HttpStatusCode.OK;

                                if (pollingUrls_ != null)
                                {
                                    string pollUrl = pollingUrls_[counter_];
                                    if (pollUrl != null)
                                    {
                                        Uri pollUri = new Uri(pollUrl);
                                        response.Headers.Location = pollUri;
                                        expectedPollUrlPath_      = pollUri.PathAndQuery;
                                    }
                                }

                                if (retryAfter_ != null)
                                {
                                    int?retryAfter = retryAfter_[counter_];
                                    if (retryAfter != null)
                                    {
                                        response.Headers.RetryAfter = RetryConditionHeaderValue.Parse(retryAfter.Value.ToString());
                                    }
                                }
                            }
                            else
                            {
                                response.StatusCode       = HttpStatusCode.Created;
                                response.Headers.Location = new Uri(CommonData.DefaultServerUrl + BASE_LOCATION + "result");
                            }
                            counter_++;
                        }
                        else if (request.Method == HttpMethod.Delete &&
                                 uri.PathAndQuery.StartsWith("/" + BASE_LOCATION + "result", StringComparison.OrdinalIgnoreCase))
                        {
                            response.StatusCode = statusCode_ ?? HttpStatusCode.OK;
                            response.Content    = new ByteArrayContent(responseBytes_);
                        }
                        else
                        {
                            response.StatusCode = statusCode_.Value;
                            if (statusCode_ == HttpStatusCode.Created)
                            {
                                response.Headers.Location = new Uri(CommonData.DefaultServerUrl + BASE_LOCATION + "result");
                            }
                            response.Content = new ByteArrayContent(responseBytes_);
                        }

                        RequestUrls.Add(uri.AbsoluteUri);
                        Timings.Add(stopwatch_.Elapsed);
                        stopwatch_.Restart();

                        return(tcs.Task);
                    }