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 void CheckInvalidParse(string input) { Assert.Throws <FormatException>(() => { RetryConditionHeaderValue.Parse(input); }); Assert.False(RetryConditionHeaderValue.TryParse(input, out RetryConditionHeaderValue result)); Assert.Null(result); }
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); }
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"); }
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); }
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"); }
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 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); } }
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); }