Refactor rate limit parser, fix locale also

This commit is contained in:
Ske 2021-02-08 19:53:06 +01:00
parent 18cf863834
commit 74424edc89
2 changed files with 72 additions and 38 deletions

View File

@ -37,7 +37,7 @@ namespace Myriad.Rest.Ratelimit
var response = await action(context, ct).ConfigureAwait(continueOnCapturedContext);
// Update rate limit state with headers
var headers = new RatelimitHeaders(response);
var headers = RatelimitHeaders.Parse(response);
_ratelimiter.HandleResponse(headers, endpoint, major);
return response;

View File

@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Linq;
using System.Net.Http;
@ -6,46 +7,79 @@ namespace Myriad.Rest.Ratelimit
{
public record RatelimitHeaders
{
public RatelimitHeaders() { }
private const string LimitHeader = "X-RateLimit-Limit";
private const string RemainingHeader = "X-RateLimit-Remaining";
private const string ResetHeader = "X-RateLimit-Reset";
private const string ResetAfterHeader = "X-RateLimit-Reset-After";
private const string BucketHeader = "X-RateLimit-Bucket";
private const string GlobalHeader = "X-RateLimit-Global";
public bool Global { get; private set; }
public int? Limit { get; private set; }
public int? Remaining { get; private set; }
public DateTimeOffset? Reset { get; private set; }
public TimeSpan? ResetAfter { get; private set; }
public string? Bucket { get; private set; }
public RatelimitHeaders(HttpResponseMessage response)
{
ServerDate = response.Headers.Date;
if (response.Headers.TryGetValues("X-RateLimit-Limit", out var limit))
if (int.TryParse(limit.First(), out var limitNum))
Limit = limitNum;
if (response.Headers.TryGetValues("X-RateLimit-Remaining", out var remaining))
if (int.TryParse(remaining!.First(), out var remainingNum))
Remaining = remainingNum;
if (response.Headers.TryGetValues("X-RateLimit-Reset", out var reset))
if (double.TryParse(reset!.First(), out var resetNum))
Reset = DateTimeOffset.FromUnixTimeMilliseconds((long) (resetNum * 1000));
if (response.Headers.TryGetValues("X-RateLimit-Reset-After", out var resetAfter))
if (double.TryParse(resetAfter!.First(), out var resetAfterNum))
ResetAfter = TimeSpan.FromSeconds(resetAfterNum);
if (response.Headers.TryGetValues("X-RateLimit-Bucket", out var bucket))
Bucket = bucket.First();
if (response.Headers.TryGetValues("X-RateLimit-Global", out var global))
if (bool.TryParse(global!.First(), out var globalBool))
Global = globalBool;
}
public bool Global { get; init; }
public int? Limit { get; init; }
public int? Remaining { get; init; }
public DateTimeOffset? Reset { get; init; }
public TimeSpan? ResetAfter { get; init; }
public string? Bucket { get; init; }
public DateTimeOffset? ServerDate { get; init; }
public DateTimeOffset? ServerDate { get; private set; }
public bool HasRatelimitInfo =>
Limit != null && Remaining != null && Reset != null && ResetAfter != null && Bucket != null;
public RatelimitHeaders() { }
public static RatelimitHeaders Parse(HttpResponseMessage response)
{
var headers = new RatelimitHeaders
{
ServerDate = response.Headers.Date,
Limit = TryGetInt(response, LimitHeader),
Remaining = TryGetInt(response, RemainingHeader),
Bucket = TryGetHeader(response, BucketHeader)
};
var resetTimestamp = TryGetDouble(response, ResetHeader);
if (resetTimestamp != null)
headers.Reset = DateTimeOffset.FromUnixTimeMilliseconds((long) (resetTimestamp.Value * 1000));
var resetAfterSeconds = TryGetDouble(response, ResetAfterHeader);
if (resetAfterSeconds != null)
headers.ResetAfter = TimeSpan.FromSeconds(resetAfterSeconds.Value);
var global = TryGetHeader(response, GlobalHeader);
if (global != null && bool.TryParse(global, out var globalBool))
headers.Global = globalBool;
return headers;
}
private static string? TryGetHeader(HttpResponseMessage response, string headerName)
{
if (!response.Headers.TryGetValues(headerName, out var values))
return null;
return values.FirstOrDefault();
}
private static int? TryGetInt(HttpResponseMessage response, string headerName)
{
var valueString = TryGetHeader(response, headerName);
if (!int.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
return null;
return value;
}
private static double? TryGetDouble(HttpResponseMessage response, string headerName)
{
var valueString = TryGetHeader(response, headerName);
if (!double.TryParse(valueString, NumberStyles.Float, CultureInfo.InvariantCulture, out var value))
return null;
return value;
}
}
}