Search code examples
asp.netasp.net-corerate-limiting

ASP.NET Rate Limit API with Queue Limit with partition key


I am using the below code,

            services.AddRateLimiter(rateLimiterOptions =>
            {
                rateLimiterOptions.RejectionStatusCode = StatusCodes.Status429TooManyRequests;

                rateLimiterOptions.AddPolicy(GexRateLimitingPolicies.Concurrent,
                    httpContext => RateLimitPartition.GetConcurrencyLimiter(
                        partitionKey: httpContext.User.Identity?.Name ?? httpContext.Request.GetIpAddress(),
                        factory: _ => new ConcurrencyLimiterOptions
                        {
                            PermitLimit = 1,
                            QueueLimit = 0,
                        }
                    ));
            });


..........................................
            app.UseRouting();
            
            app.UseRateLimiter();
    

................................................


        [Authorize]
        [EnableRateLimiting(GexRateLimitingPolicies.Concurrent)]
        public IActionResult MyApi()
        {

I want if same user call MyApi 2 times, he should get 429 error. But different users are allowed to call this method concurrently.

When I run the app, if different users call the same MyApi at same time then one of them will get 429 error.

Update: After changing the order of middlewares,

app.UseAuthentication();
app.UseAuthorization();

app.UseRateLimiter();

Both user get different partition key but there is no rejection. All requests are blocked/queued.

Also, if I put a breakpoint at,

RateLimitPartition.GetConcurrencyLimiter(
                        partitionKey: httpContext.User.Identity?.Name ?? httpContext.Request.GetIpAddress(),
                        factory: _ => new ConcurrencyLimiterOptions

It only hit for the second request when first request finish (for the same user).

I used Network tool to monitor and found that browser is queuing the request and send one after the other.


Solution

  • The issue was the ordering of middleware,

    app.UseAuthentication();
    app.UseAuthorization();
    
    app.UseRateLimiter();
    

    Make sure try on different browsers and Network tools instead of rely on Edge/Chrome as they queue/serilaize the requests.