diff --git a/src/Discord.Net.Rest/Net/DefaultRestClient.cs b/src/Discord.Net.Rest/Net/DefaultRestClient.cs index 7e10a27ed2..cbdeb11c4b 100644 --- a/src/Discord.Net.Rest/Net/DefaultRestClient.cs +++ b/src/Discord.Net.Rest/Net/DefaultRestClient.cs @@ -29,13 +29,9 @@ public DefaultRestClient(string baseUrl, bool useProxy = false, IWebProxy webPro _baseUrl = baseUrl; #pragma warning disable IDISP014 - _client = new HttpClient(new HttpClientHandler - { - AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, - UseCookies = false, - UseProxy = useProxy, - Proxy = webProxy - }); + var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, UseCookies = false, UseProxy = useProxy }; + if (useProxy) handler.Proxy = webProxy; + _client = new HttpClient(handler); #pragma warning restore IDISP014 SetHeader("accept-encoding", "gzip, deflate"); diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs index 1fa7494d6e..c3751d944c 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs @@ -157,7 +157,7 @@ public async Task SendAsync(RestRequest request) }*/ finally { - UpdateRateLimit(id, request, info, response.StatusCode == (HttpStatusCode)429, body: response.Stream); + UpdateRateLimit(id, request, info, response.StatusCode == (HttpStatusCode)429, restResponse: response); #if DEBUG_LIMITS Debug.WriteLine($"[{id}] Stop"); #endif @@ -316,7 +316,7 @@ private async Task EnterAsync(int id, IRequest request) } } - private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool is429, bool redirected = false, Stream body = null) + private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool is429, bool redirected = false, RestResponse restResponse = default) { if (WindowCount == 0) return; @@ -386,7 +386,7 @@ private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool _semaphore = 0; // use the payload reset after value - var payload = info.ReadRatelimitPayload(body); + var payload = info.ReadRatelimitPayload(restResponse); // fallback on stored ratelimit info when payload is null, https://github.com/discord-net/Discord.Net/issues/2123 resetTick = DateTimeOffset.UtcNow.Add(TimeSpan.FromSeconds(payload?.RetryAfter ?? info.ResetAfter?.TotalSeconds ?? 0)); diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs index 42b97661e9..a8f7a7c510 100644 --- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs +++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs @@ -61,10 +61,27 @@ internal RateLimitInfo(Dictionary headers, string endpoint) DateTimeOffset.TryParse(temp, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null; } - internal Ratelimit ReadRatelimitPayload(Stream response) + internal Ratelimit ReadRatelimitPayload(RestResponse restResponse) { - if (response != null && response.Length != 0) + var response = restResponse.Stream; + if (response != null && response.Length != 0 && response.CanRead) { + var pos = response.Position; + using (TextReader text = new StreamReader(response)) + { + if (text.ReadToEnd().StartsWith("<")) + { + return new Ratelimit + { + Global = true, + Message = "Cloudflare HTML limit", + RetryAfter = restResponse.Headers.TryGetValue("Retry-After", out var retry) ? float.Parse(retry) : 60 * 30 // 30 mins + }; + } + } + + response.Position = pos; + using (TextReader text = new StreamReader(response)) using (JsonReader reader = new JsonTextReader(text)) {