question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Rate limiting middleware - Statistics about rate limiters

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

The ASP.NET Core rate limiting middleware is great, but “limited” in terms of what you an communicate with your users. Let’s start with some code that you can write today in .NET 7:

builder.Services.AddRateLimiter(options =>
{
    options.OnRejected = async (context, token) =>
    {
        context.HttpContext.Response.StatusCode = 429;
        if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
        {
            await context.HttpContext.Response.WriteAsync(
                $"Too many requests. Please try again after {retryAfter.TotalMinutes} minute(s). " +
                $"Read more about our rate limits at https://example.org/docs/ratelimiting.", cancellationToken: token);
        }
        else
        {
            await context.HttpContext.Response.WriteAsync(
                "Too many requests. Please try again later. " +
                "Read more about our rate limits at https://example.org/docs/ratelimiting.", cancellationToken: token);
        }
    };

    // ...
});

When rate limits are triggered, a response is returned that tells the user they are rate limited, where to find more information, and (if the MetadataName.RetryAfter data is available), when to retry.

This is quite limited. There’s no access to which rate limiter fired, and what its statistics are.

Additionally, the current RateLimitLease is only accessible when rate limiting is fired - not for every request. If you would want to return statistics about your limits (e.g. like GitHub does), you’ll find it impossible to get statistics about the current lease in a custom middleware that can write out these additional headers.

Describe the solution you’d like

Here’s a middleware that has access to some of data that I’d want to access:

public class RateLimitStatisticsMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IOptions<RateLimiterOptions> _options;

    public RateLimitStatisticsMiddleware(RequestDelegate next, IOptions<RateLimiterOptions> options)
    {
        _next = next;
        _options = options;
    }

    public Task Invoke(HttpContext context)
    {
        // Note: This should also work on endpoint limiters, but those are not available.
        // There is no current "rate limit context" of sorts. Including the policy name etc.
        var globalLimiter = _options.Value.GlobalLimiter;
        if (globalLimiter != null)
        {
            var statistics = globalLimiter.GetStatistics(context);
            if (statistics != null)
            {
                // Note: It would be great to be able to get the TokenLimit from the "current rate limiter context"
                context.Response.Headers.Add("X-Rate-Limit-Limit", "20");

                // Note: It would be great to be able to get the Window from the "current rate limiter context"
                context.Response.Headers.Add("X-Rate-Limit-Reset", DateTimeOffset.UtcNow.ToString("O"));

                // This one is there today
                context.Response.Headers.Add("X-Rate-Limit-Remaining", statistics.CurrentAvailablePermits.ToString());
            }
        }

        return _next(context);
    }
}

The dream scenario for a better ASP.NET Core rate limiter middleware would be to:

  • Have access to more statistics about the rate limiter (which policy fired, what partition, what are the limiter’s options so I can emit a message that says “you can only make 10 requests per minute”, …) in the rejected callbacks.
  • Have a feature on the current HttpContext that gives access to the current rate limit context, so these details can also be returned on successful requests, or added to telemetry.

Additional context

Most rate limiters in System.Threading.RateLimiting don’t provide additional statistics. This feature will need changes in both ASP.NET Core and the .NET framework.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:39
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

5reactions
wtgodbecommented, Sep 26, 2022

I definitely think we should do this for dotnet 8

1reaction
anandsowmcommented, Dec 27, 2022

Yes, would be very useful feature. Looking at the different classes involved, there is no way to know how many permits have been issued so far for a given partition key. That would be good to have. Also is there a way to retain the count of leases issued between system restarts? It is right now stored in-memory, try to provide a way to plug in a persistence component.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Rate limiting middleware in ASP.NET Core
The concurrency limiter limits only the number of concurrent requests and doesn't cap the number of requests in a time period. The cost...
Read more >
ASP.NET Core rate limiting middleware in .NET 7
Rate limiting is a way to control the amount of traffic that a web application or API receives, by limiting the number of...
Read more >
The Fundamentals of Rate Limiting: How it Works and Why ...
Rate limiters are a way to limit the number of requests that can be made to a specific endpoint. This is useful for...
Read more >
API Rate Limiter System Design
We construct a rate limiter middleware, which throttles requests to your APIs, rather than establishing a rate limiter on the API servers, as...
Read more >
Rate Limiter For The Real World - by Alex Xu
This method allows for rate limiting integration within our application code as middleware. It offers customization for different use-cases and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found