public void CanPopulateObjectFromSerializedData() { var headers = new Dictionary <string, string> { { "X-RateLimit-Limit", "100" }, { "X-RateLimit-Remaining", "42" }, { "X-RateLimit-Reset", "1372700873" } }; var response = CreateResponse(HttpStatusCode.Forbidden, headers); var exception = new RateLimitExceededException(response); using (var stream = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(stream, exception); stream.Position = 0; var deserialized = (RateLimitExceededException)formatter.Deserialize(stream); Assert.Equal(HttpStatusCode.Forbidden, deserialized.StatusCode); Assert.Equal(100, deserialized.Limit); Assert.Equal(42, deserialized.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, deserialized.Reset); } }
public void RetryAfter_Equals_CtorRetryAfterParameter() { var testValue = 100.Seconds(); var e = new RateLimitExceededException(testValue); Assert.Equal(testValue, e.RetryAfter); }
public void Message_ContainsCorrectText() { var testValue = 100.Seconds(); var e = new RateLimitExceededException(testValue); Assert.Equal("Rate limit exceeded", e.Message); }
public void Exception_ResponseMessageConstructor() { var response = new RiotResponse(null); var message = "TEST"; var ex1 = new RestException(response, message); Assert.That(ex1.Response, Is.EqualTo(response)); Assert.That(ex1.Message, Is.EqualTo(message)); var ex2 = new NotFoundException(response, message); Assert.That(ex2.Response, Is.EqualTo(response)); Assert.That(ex2.Message, Is.EqualTo(message)); var ex3 = new RateLimitExceededException(response, message); Assert.That(ex3.Response, Is.EqualTo(response)); Assert.That(ex3.Message, Is.EqualTo(message)); var ex4 = new RestTimeoutException(response, message); Assert.That(ex4.Response, Is.EqualTo(response)); Assert.That(ex4.Message, Is.EqualTo(message)); var ex5 = new ConnectionFailedException(response, message); Assert.That(ex5.Response, Is.EqualTo(response)); Assert.That(ex5.Message, Is.EqualTo(message)); }
public void ReturnsSkewedDistanceFromReset() { // One hour into the future is hopefully long enough to still be // in the future at the end of this method var resetTime = DateTimeOffset.Now + TimeSpan.FromHours(1); var recvDate = new DateTimeOffset(2020, 06, 07, 12, 00, 00, TimeSpan.Zero); var skew = TimeSpan.FromSeconds(-5); var response = CreateResponse(HttpStatusCode.Forbidden, new Dictionary <string, string> { ["X-RateLimit-Limit"] = "100", ["X-RateLimit-Remaining"] = "0", ["X-RateLimit-Reset"] = resetTime.ToUnixTimeSeconds() .ToString(CultureInfo.InvariantCulture), ["Date"] = (recvDate + skew).ToString("r"), [ApiInfoParser.ReceivedTimeHeaderName] = recvDate.ToString("r"), }); Assert.Equal(skew, response.ApiInfo.ServerTimeDifference); var except = new RateLimitExceededException(response); var timeToReset = except.GetRetryAfterTimeSpan(); Assert.NotEqual(TimeSpan.Zero, timeToReset); Assert.InRange(timeToReset, TimeSpan.Zero, TimeSpan.FromHours(1)); }
public void HandlesInvalidHeaderValues() { var headers = new Dictionary <string, string> { { "X-RateLimit-Limit", "XXX" }, { "X-RateLimit-Remaining", "XXXX" }, { "X-RateLimit-Reset", "XXXX" }, { "Date", "XXX" }, { ApiInfoParser.ReceivedTimeHeaderName, "XXX" }, }; var response = CreateResponse(HttpStatusCode.Forbidden, headers); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Thu 01 Jan 1970 0:00:00 AM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, exception.Reset); Assert.Equal(TimeSpan.Zero, exception.GetRetryAfterTimeSpan()); }
public void Exception_DefaultConstructor() { var ex1 = new RestException(); Assert.That(ex1.Response, Is.EqualTo(null)); Assert.That(ex1.Message, Is.EqualTo("A REST request failed.")); Assert.That(ex1.InnerException, Is.Null); var ex2 = new NotFoundException(); Assert.That(ex2.Response, Is.EqualTo(null)); Assert.That(ex2.Message, Is.EqualTo("The requested resource was not found.")); Assert.That(ex2.InnerException, Is.Null); var ex3 = new RateLimitExceededException(); Assert.That(ex3.Response, Is.EqualTo(null)); Assert.That(ex3.Message, Is.EqualTo("The rate limit for the current API key was exceeded.")); Assert.That(ex3.InnerException, Is.Null); var ex4 = new RestTimeoutException(); Assert.That(ex4.Response, Is.EqualTo(null)); Assert.That(ex4.Message, Is.EqualTo("A REST request timed out.")); Assert.That(ex4.InnerException, Is.Null); var ex5 = new ConnectionFailedException(); Assert.That(ex5.Response, Is.EqualTo(null)); Assert.That(ex5.Message, Is.EqualTo("Failed to connect to the server.")); Assert.That(ex5.InnerException, Is.Null); }
ObjectResult RateLimit(RateLimitExceededException exception) { Logger.LogWarning(exception, "Exceeded GitHub rate limit!"); var secondsString = Math.Ceiling((exception.Reset - DateTimeOffset.Now).TotalSeconds).ToString(CultureInfo.InvariantCulture); Response.Headers.Add("Retry-After", new StringValues(secondsString)); return(StatusCode(HttpStatusCode.TooManyRequests, new ErrorMessage(ErrorCode.GitHubApiRateLimit))); }
StatusCodeResult RateLimit(RateLimitExceededException exception) { Logger.LogWarning("Exceeded GitHub rate limit! Exception {0}", exception); var secondsString = Math.Ceiling((exception.Reset - DateTimeOffset.Now).TotalSeconds).ToString(CultureInfo.InvariantCulture); Response.Headers.Add("Retry-After", new StringValues(secondsString)); return(StatusCode(429)); }
public void HandlesMissingHeaderValues() { var response = new Response(HttpStatusCode.Forbidden, null, new Dictionary <string, string>(), "application/json"); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = new DateTimeOffset(DateTime.UtcNow.CeilingSecond()); Assert.Equal(expectedReset, exception.Reset); }
/// <summary> /// 429 response for a given <paramref name="rateLimitException"/>. /// </summary> /// <param name="rateLimitException">The <see cref="RateLimitExceededException"/> that occurred.</param> /// <returns>A <see cref="HttpStatusCode.TooManyRequests"/> <see cref="ObjectResult"/>.</returns> protected ObjectResult RateLimit(RateLimitExceededException rateLimitException) { if (rateLimitException == null) { throw new ArgumentNullException(nameof(rateLimitException)); } Logger.LogWarning(rateLimitException, "Exceeded GitHub rate limit!"); var secondsString = Math.Ceiling((rateLimitException.Reset - DateTimeOffset.UtcNow).TotalSeconds).ToString(CultureInfo.InvariantCulture); Response.Headers.Add(HeaderNames.RetryAfter, secondsString); return(StatusCode(HttpStatusCode.TooManyRequests, new ErrorMessageResponse(ErrorCode.GitHubApiRateLimit))); }
public void HandlesMissingHeaderValues() { var response = new Response(HttpStatusCode.Forbidden, null, new Dictionary<string, string>(), "application/json"); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Thu 01 Jan 1970 0:00:00 AM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, exception.Reset); }
public void HandlesMissingHeaderValues() { var response = CreateResponse(HttpStatusCode.Forbidden); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Thu 01 Jan 1970 0:00:00 AM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, exception.Reset); }
public void HandlesMissingHeaderValues() { var response = new ApiResponse<object> { StatusCode = HttpStatusCode.Forbidden }; response.ApiInfo = CreateApiInfo(response); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Thu 01 Jan 1970 0:00:00 AM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, exception.Reset); }
public void HandlesInvalidHeaderValues() { var headers = new Dictionary <string, string> { { "X-RateLimit-Limit", "XXX" }, { "X-RateLimit-Remaining", "XXXX" }, { "X-RateLimit-Reset", "XXXX" } }; var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json"); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = new DateTimeOffset(DateTime.UtcNow.CeilingSecond()); Assert.Equal(expectedReset, exception.Reset); }
public void ParsesRateLimitsFromHeaders() { var headers = new Dictionary <string, string> { { "X-RateLimit-Limit", "100" }, { "X-RateLimit-Remaining", "42" }, { "X-RateLimit-Reset", "49" } }; var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json"); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(100, exception.Limit); Assert.Equal(42, exception.Remaining); var expectedReset = DateTime.UtcNow.CeilingSecond().AddSeconds(49); Assert.Equal("API Rate Limit exceeded", exception.Message); Assert.Equal(expectedReset, exception.Reset); }
public void ParsesRateLimitsFromHeaders() { var response = new ApiResponse<object> { StatusCode = HttpStatusCode.Forbidden }; response.Headers.Add("X-RateLimit-Limit", "100"); response.Headers.Add("X-RateLimit-Remaining", "42"); response.Headers.Add("X-RateLimit-Reset", "1372700873"); response.ApiInfo = CreateApiInfo(response); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(100, exception.Limit); Assert.Equal(42, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal("API Rate Limit exceeded", exception.Message); Assert.Equal(expectedReset, exception.Reset); }
public void HandlesInvalidHeaderValues() { var response = new ApiResponse <object> { StatusCode = HttpStatusCode.Forbidden }; response.Headers.Add("X-RateLimit-Limit", "XXX"); response.Headers.Add("X-RateLimit-Remaining", "XXXX"); response.Headers.Add("X-RateLimit-Reset", "XXXX"); response.ApiInfo = CreateApiInfo(response); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Thu 01 Jan 1970 0:00:00 AM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, exception.Reset); }
public void ParsesRateLimitsFromHeaders() { var headers = new Dictionary<string, string> { {"X-RateLimit-Limit", "100"}, {"X-RateLimit-Remaining", "42"}, {"X-RateLimit-Reset", "1372700873"} }; var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json"); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(100, exception.Limit); Assert.Equal(42, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal("API Rate Limit exceeded", exception.Message); Assert.Equal(expectedReset, exception.Reset); }
public void HandlesInvalidHeaderValues() { var headers = new Dictionary <string, string> { { "X-RateLimit-Limit", "XXX" }, { "X-RateLimit-Remaining", "XXXX" }, { "X-RateLimit-Reset", "XXXX" } }; var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json"); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(0, exception.Limit); Assert.Equal(0, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Thu 01 Jan 1970 0:00:00 AM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, exception.Reset); }
public void ParsesRateLimitsFromHeaders() { var response = new ApiResponse <object> { StatusCode = HttpStatusCode.Forbidden }; response.Headers.Add("X-RateLimit-Limit", "100"); response.Headers.Add("X-RateLimit-Remaining", "42"); response.Headers.Add("X-RateLimit-Reset", "1372700873"); response.ApiInfo = CreateApiInfo(response); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(100, exception.Limit); Assert.Equal(42, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal("API Rate Limit exceeded", exception.Message); Assert.Equal(expectedReset, exception.Reset); }
public void ReturnsZeroIfSkewedResetInPast() { var beginTime = DateTimeOffset.Now; var resetTime = beginTime - TimeSpan.FromHours(1); var response = CreateResponse(HttpStatusCode.Forbidden, new Dictionary <string, string> { ["X-RateLimit-Limit"] = "100", ["X-RateLimit-Remaining"] = "0", ["X-RateLimit-Reset"] = resetTime.ToUnixTimeSeconds() .ToString(CultureInfo.InvariantCulture), ["Date"] = beginTime.ToString("r"), [ApiInfoParser.ReceivedTimeHeaderName] = beginTime.ToString("r"), }); Assert.Equal(TimeSpan.Zero, response.ApiInfo.ServerTimeDifference); var except = new RateLimitExceededException(response); var timeToReset = except.GetRetryAfterTimeSpan(); Assert.Equal(TimeSpan.Zero, timeToReset); }
public void ParsesRateLimitsFromHeaders() { var headers = new Dictionary <string, string> { { "X-RateLimit-Limit", "100" }, { "X-RateLimit-Remaining", "42" }, { "X-RateLimit-Reset", "1372700873" } }; var response = CreateResponse(HttpStatusCode.Forbidden, headers); var exception = new RateLimitExceededException(response); Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode); Assert.Equal(100, exception.Limit); Assert.Equal(42, exception.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal("API Rate Limit exceeded", exception.Message); Assert.Equal(expectedReset, exception.Reset); }
public void Exception_ResponseConstructor() { var response = new RiotResponse(new HttpResponseMessage(System.Net.HttpStatusCode.OK)); var ex1 = new RestException(response); Assert.That(ex1.Response, Is.EqualTo(response)); var ex2 = new NotFoundException(response); Assert.That(ex2.Response, Is.EqualTo(response)); var ex3 = new RateLimitExceededException(response); Assert.That(ex3.Response, Is.EqualTo(response)); var ex4 = new RestTimeoutException(response); Assert.That(ex4.Response, Is.EqualTo(response)); var ex5 = new ConnectionFailedException(response); Assert.That(ex5.Response, Is.EqualTo(response)); }
public void Exception_ResponseConstructor_NullHttpResponse() { var response = new RiotResponse(null); var ex1 = new RestException(response); Assert.That(ex1.Response, Is.EqualTo(response)); var ex2 = new NotFoundException(response); Assert.That(ex2.Response, Is.EqualTo(response)); var ex3 = new RateLimitExceededException(response); Assert.That(ex3.Response, Is.EqualTo(response)); var ex4 = new RestTimeoutException(response); Assert.That(ex4.Response, Is.EqualTo(response)); var ex5 = new ConnectionFailedException(response); Assert.That(ex5.Response, Is.EqualTo(response)); }
public void Is_HaveIBeenPwnedClientException() { var e = new RateLimitExceededException(1.Seconds()); Assert.IsAssignableFrom <HaveIBeenPwnedClientException>(e); }
internal async Task <HttpResponse> GetAsync(string url, CancellationToken token, IProgress <double> progress = null) { HttpResponseMessage resp = await Client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false); if ((int)resp.StatusCode == 429) { var ex = new RateLimitExceededException(resp); if (Options.HandleRateLimits == false) { throw ex; } RateLimitInfo info = ex.RateLimit; TimeSpan diff = info.Reset - DateTime.Now; int millis = (int)diff.TotalMilliseconds; if (millis > 0) { await Task.Delay(millis).ConfigureAwait(false); } return(await GetAsync(url, token, progress).ConfigureAwait(false)); } if (token.IsCancellationRequested) { throw new TaskCanceledException(); } using MemoryStream ms = new MemoryStream(); using Stream s = await resp.Content.ReadAsStreamAsync().ConfigureAwait(false); byte[] buffer = new byte[1 << 13]; int bytesRead; long?contentLength = resp.Content.Headers.ContentLength; long totalRead = 0; progress?.Report(0); while ((bytesRead = await s.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0) { if (token.IsCancellationRequested) { throw new TaskCanceledException(); } if (contentLength != null) { double prog = (double)totalRead / (double)contentLength; progress?.Report(prog); } await ms.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false); totalRead += bytesRead; } progress?.Report(1); byte[] bytes = ms.ToArray(); return(new HttpResponse(resp, bytes)); }
public void CanPopulateObjectFromSerializedData() { var response = new ApiResponse<object> { StatusCode = HttpStatusCode.Forbidden }; response.Headers.Add("X-RateLimit-Limit", "100"); response.Headers.Add("X-RateLimit-Remaining", "42"); response.Headers.Add("X-RateLimit-Reset", "1372700873"); response.ApiInfo = CreateApiInfo(response); var exception = new RateLimitExceededException(response); using (var stream = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(stream, exception); stream.Position = 0; var deserialized = (RateLimitExceededException)formatter.Deserialize(stream); Assert.Equal(HttpStatusCode.Forbidden, deserialized.StatusCode); Assert.Equal(100, deserialized.Limit); Assert.Equal(42, deserialized.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, deserialized.Reset); } }
public void CanPopulateObjectFromSerializedData() { var headers = new Dictionary<string, string>{ {"X-RateLimit-Limit", "100"}, {"X-RateLimit-Remaining", "42"}, {"X-RateLimit-Reset", "1372700873"} }; var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json"); var exception = new RateLimitExceededException(response); using (var stream = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(stream, exception); stream.Position = 0; var deserialized = (RateLimitExceededException)formatter.Deserialize(stream); Assert.Equal(HttpStatusCode.Forbidden, deserialized.StatusCode); Assert.Equal(100, deserialized.Limit); Assert.Equal(42, deserialized.Remaining); var expectedReset = DateTimeOffset.ParseExact( "Mon 01 Jul 2013 5:47:53 PM -00:00", "ddd dd MMM yyyy h:mm:ss tt zzz", CultureInfo.InvariantCulture); Assert.Equal(expectedReset, deserialized.Reset); } }