I am implementing ASP.NET Core rate limiting, per fixed window:
builder.Services.AddRateLimiter(options =>
{
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
{
var remoteIpAddress = httpContext.Connection.RemoteIpAddress;
var localIpAddress = httpContext.Connection.LocalIpAddress;
var partitionKey = $"{remoteIpAddress} {localIpAddress}";
return RateLimitPartition.GetFixedWindowLimiter(partitionKey, options => new FixedWindowRateLimiterOptions
{
AutoReplenishment = true,
PermitLimit = 10,
QueueLimit = 0,
Window = TimeSpan.FromMinutes(1),
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});
});
options.OnRejected = async (context, cancellationToken) =>
{
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
{
context.HttpContext.Response.Headers.RetryAfter = ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
}
context.HttpContext.Response.Redirect("/RateLimitExceeded", false);
};
});
As you can see, I want to redirect to some URL, in this case, it's a Razor page, and, of course, I don't want it to be involved in the rate limiting process, so I add a [DisableRateLimiting]
attribute to the model:
[DisableRateLimiting]
public class RateLimitExceededModel : PageModel
{
public void OnGet() { }
}
However, try as I might, I can't get this too work, meaning, when the limit is reached, I always get an ERR_TOO_MANY_REDIRECTS
error, which means I somehow entered a redirect loop.
How can I make this work, that is, redirect to a custom page that is exempt from rate limiting?
There's nothing wrong with the codes you provided,notice the order of the middlwares,app.UseRateLimiter();
should be placed after Routing middlware.
I tried to reproduce the issue with your codes.If the middlewares are in the correct order,it works well:
but if the middlewares are not in correct order: