C
C#4mo ago
Angius

✅ Rate limiting no worky

Got rate limiting all set up:
public static class RateLimiting
{
public const string Rss = nameof(Rss);
public const string Quotes = nameof(Quotes);
public const string Reports = nameof(Reports);

public static IServiceCollection AddRateLimiting(this IServiceCollection services)
{
return services.AddRateLimiter(x => x
.AddFixedWindowLimiter(policyName: Rss, options => {
options.Window = TimeSpan.FromHours(1);
})
.AddFixedWindowLimiter(policyName: Quotes, options => {
options.Window = TimeSpan.FromSeconds(10);
})
.AddFixedWindowLimiter(policyName: Reports, options => {
options.Window = TimeSpan.FromHours(1);
options.PermitLimit = 3;
})
);
}
}
public static class RateLimiting
{
public const string Rss = nameof(Rss);
public const string Quotes = nameof(Quotes);
public const string Reports = nameof(Reports);

public static IServiceCollection AddRateLimiting(this IServiceCollection services)
{
return services.AddRateLimiter(x => x
.AddFixedWindowLimiter(policyName: Rss, options => {
options.Window = TimeSpan.FromHours(1);
})
.AddFixedWindowLimiter(policyName: Quotes, options => {
options.Window = TimeSpan.FromSeconds(10);
})
.AddFixedWindowLimiter(policyName: Reports, options => {
options.Window = TimeSpan.FromHours(1);
options.PermitLimit = 3;
})
);
}
}
and registered
services.AddRateLimiting();
services.AddRateLimiting();
app.UseRateLimiter();
app.UseRateLimiter();
got rate limiting set on an endpoint:
using ReturnType = Results<NotFound, Ok<QuoteDto>>;

[Handler]
[MapGet("api/quotes/random")]
public static partial class GetRandomQuote
{
internal static void CustomizeEndpoint(IEndpointConventionBuilder endpoint) => endpoint
.RequireRateLimiting(RateLimiting.Quotes);

[UsedImplicitly]
public sealed record Query;

private static async ValueTask<ReturnType> HandleAsync(Query _, ApplicationDbContext context, CancellationToken cancellationToken)
{
var quote = await context.Database.SqlQueryRaw<QuoteDto>("""
SELECT q."Author", q."Body"
FROM "Quotes" q
TABLESAMPLE SYSTEM_ROWS(1)
LIMIT 1
""")
.FirstOrDefaultAsync(cancellationToken);

return quote is null ? TypedResults.NotFound() : TypedResults.Ok(quote);
}
}
using ReturnType = Results<NotFound, Ok<QuoteDto>>;

[Handler]
[MapGet("api/quotes/random")]
public static partial class GetRandomQuote
{
internal static void CustomizeEndpoint(IEndpointConventionBuilder endpoint) => endpoint
.RequireRateLimiting(RateLimiting.Quotes);

[UsedImplicitly]
public sealed record Query;

private static async ValueTask<ReturnType> HandleAsync(Query _, ApplicationDbContext context, CancellationToken cancellationToken)
{
var quote = await context.Database.SqlQueryRaw<QuoteDto>("""
SELECT q."Author", q."Body"
FROM "Quotes" q
TABLESAMPLE SYSTEM_ROWS(1)
LIMIT 1
""")
.FirstOrDefaultAsync(cancellationToken);

return quote is null ? TypedResults.NotFound() : TypedResults.Ok(quote);
}
}
and yet I can spam it ad infinitum and rate limiting never triggers. What gives?
28 Replies
FestivalDelGelato
did you exclude using the EnableRateLimiting attribute?
Angius
AngiusOP4mo ago
That's for controllers, IIRC, not for minimal APIs, which is what Immediate.Apis is based on
FestivalDelGelato
yeh i was looking at the second part of the code, seeing a bunch of statics and going wtf for a minute
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
SG97
SG974mo ago
they have PermitLimit = 3
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
SG97
SG974mo ago
ah
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
:KEKW: Seems like, what, the code doesn't even run?
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
I did
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
Worth a shot ig
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
The breakpoint in this extension method itself does get hit, so at least I can tell I'm calling it correctly
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
All small ones get hit
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
All of those are hit, in order
No description
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
No description
Angius
AngiusOP4mo ago
Curiously, the FixedWindowRateLimiterOptions I have does not have a constructor Did you check it in 9.0 source? I'm on 8.0 I'll set permit limit explicitly and see Nope, even setting it explicitly to 1 still allows me to spam that endpoint
Angius
AngiusOP4mo ago
Queue limit "must" be set as well, it seems:
No description
Angius
AngiusOP4mo ago
No cigar I set every option explicitly and it still doesn't work huh ah Middleware order I had app.UseRateLimite() near the beginning of the middleware stack Moved it right in front of .UseEndpoints() That did the trick Too bad it returns... drumroll... 503 Instead of 429 as it should
FestivalDelGelato
but that's an entire other class of errors, it seems weird
Angius
AngiusOP4mo ago
Status code is easily fixable at least But yeah, really seems like this whole middleware is... not all that well made? "Must be set to >1" and then no validation
Unknown User
Unknown User4mo ago
Message Not Public
Sign In & Join Server To View
Angius
AngiusOP4mo ago
My UseRouting() is explicit thankfully So we're gucci

Did you find this page helpful?