Wiaoj.RateLimiting.AspNetCore
0.0.1-alpha.99-preview
This is a prerelease version of Wiaoj.RateLimiting.AspNetCore.
dotnet add package Wiaoj.RateLimiting.AspNetCore --version 0.0.1-alpha.99-preview
NuGet\Install-Package Wiaoj.RateLimiting.AspNetCore -Version 0.0.1-alpha.99-preview
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Wiaoj.RateLimiting.AspNetCore" Version="0.0.1-alpha.99-preview" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Wiaoj.RateLimiting.AspNetCore" Version="0.0.1-alpha.99-preview" />
<PackageReference Include="Wiaoj.RateLimiting.AspNetCore" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Wiaoj.RateLimiting.AspNetCore --version 0.0.1-alpha.99-preview
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Wiaoj.RateLimiting.AspNetCore, 0.0.1-alpha.99-preview"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Wiaoj.RateLimiting.AspNetCore@0.0.1-alpha.99-preview
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Wiaoj.RateLimiting.AspNetCore&version=0.0.1-alpha.99-preview&prerelease
#tool nuget:?package=Wiaoj.RateLimiting.AspNetCore&version=0.0.1-alpha.99-preview&prerelease
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Wiaoj.RateLimiting.AspNetCore
ASP.NET Core integration package for Wiaoj.RateLimiting, providing HTTP middleware, partition key extractors, endpoint metadata conventions, and RFC-compliant response handling.
Installation
dotnet add package Wiaoj.RateLimiting.AspNetCore
What This Package Contains
RateLimitingMiddleware: ASP.NET Core middleware that evaluates incoming requests against configured named or default rate limiting policies, applies endpoint costs, and emits RFC-standard responses.- Key Selectors (
IRateLimitKeySelector):ClientIpKeySelector: Formats remote IPv4/IPv6 addresses directly using stack-allocated buffers.ApiKeyHeaderKeySelector: Extracts identity keys from configurable request headers (e.g.X-Api-Key), with configurable fallback selectors.UserClaimKeySelector: Extracts identity keys from authenticated claims (ClaimsPrincipal), with configurable fallback selectors.
- Endpoint Metadata and Route Conventions:
[DisableRateLimiting]/.DisableRateLimiting(): Bypasses rate limiting for targeted endpoints.[RateLimitCost(int)]/.WithRateLimitCost(int): Statically overrides the quota cost for an endpoint..WithRateLimitCost(Func<HttpContext, int>): Dynamically computes quota cost at runtime (e.g. from batch payload counts or query parameters).
- RFC and Standards Compliance:
- RFC 6585: Emits HTTP
429 Too Many Requests. - RFC 9110: Emits integer delta-seconds
Retry-Afterheader. - RFC 7807 / RFC 9457: Serializes
application/problem+jsonProblemDetailsresponses. - IETF Draft Headers: Writes
RateLimit-RemainingandRateLimit-Resetheaders.
- RFC 6585: Emits HTTP
Setup and Configuration
1. Register Services in Program.cs
using Wiaoj.DistributedCounter;
using Wiaoj.RateLimiting;
using Wiaoj.RateLimiting.AspNetCore;
using Wiaoj.RateLimiting.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Configure counter backend
builder.Services.AddDistributedCounter(dc => dc.UseInMemory());
// Configure rate limiting policies and ASP.NET Core options
builder.Services.AddWiaojRateLimiting(limiter => {
limiter.AddPolicy("auth", policy => policy.UseFixedWindow(limit: 5, window: TimeSpan.FromMinutes(1)));
limiter.UseDefaultPolicy(policy => policy.UseSlidingWindow(limit: 100, window: TimeSpan.FromMinutes(1)));
limiter.WithAspNetCore(options => {
options.KeySelector = new ClientIpKeySelector(prefix: "ip:");
options.StatusCode = StatusCodes.Status429TooManyRequests;
options.EnableIetfHeaders = true;
options.UseProblemDetails = true;
});
});
var app = builder.Build();
// Enable the middleware in the request pipeline
app.UseWiaojRateLimiting();
Endpoint Routing Conventions
Static Costing, Dynamic Costing, and Exemptions
// 1. Endpoint with static custom cost (consumes 5 quota units per call)
app.MapPost("/api/export", () => Results.Ok())
.WithRateLimitCost(5);
// 2. Endpoint with dynamic cost calculated from query parameters
app.MapPost("/api/batch", (int batchSize) => Results.Ok())
.WithRateLimitCost(ctx => {
if (ctx.Request.Query.TryGetValue("batchSize", out var val) && int.TryParse(val, out int count)) {
return Math.Max(1, count);
}
return 1;
});
// 3. Endpoint exempt from all rate limiting
app.MapGet("/healthz", () => Results.Ok("OK"))
.DisableRateLimiting();
Key Selectors
Key selectors define how client identity is extracted from HttpContext:
limiter.WithAspNetCore(options => {
// 1. Client IP address (IPv4 / IPv6)
options.KeySelector = new ClientIpKeySelector(prefix: "ip:");
// 2. API Key header with fallback to IP if missing
options.KeySelector = new ApiKeyHeaderKeySelector(
headerName: "X-Api-Key",
prefix: "api_key:",
fallbackSelector: new ClientIpKeySelector("anon_ip:"));
// 3. User claim (Subject ID) with fallback to IP if unauthenticated
options.KeySelector = new UserClaimKeySelector(
claimType: ClaimTypes.NameIdentifier,
prefix: "user:",
fallbackSelector: new ClientIpKeySelector("anon_ip:"));
});
Response Formatting & ProblemDetails
When a request is rejected, the middleware formats the response according to configured options:
Standard RFC 7807 Response Body (application/problem+json)
{
"type": "https://tools.ietf.org/html/rfc6585#section-4",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded. Quota will be available in 12 seconds.",
"instance": "/api/orders",
"retryAfter": 12,
"remaining": 0
}
Customizing ProblemDetails
limiter.WithAspNetCore(options => {
options.UseProblemDetails = true;
options.ProblemDetailsCustomizer = (problem, context, decision) => {
problem.Extensions["traceId"] = context.TraceIdentifier;
problem.Extensions["policy"] = "auth";
};
});
Custom Low-Level Rejection Callback
limiter.WithAspNetCore(options => {
options.OnRejectedAsync = (context, decision) => {
context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
return context.Response.WriteAsync("Custom plain-text rate limit rejection.");
};
});
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- Wiaoj.Preconditions (>= 0.0.1-alpha.99-preview)
- Wiaoj.RateLimiting (>= 0.0.1-alpha.99-preview)
- Wiaoj.RateLimiting.Abstractions (>= 0.0.1-alpha.99-preview)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-alpha.99-preview | 57 | 9/6/2026 |
| 0.0.1-alpha.98-preview | 53 | 9/6/2026 |
| 0.0.1-alpha.97-preview | 52 | 9/6/2026 |
| 0.0.1-alpha.96-preview | 49 | 9/6/2026 |
| 0.0.1-alpha.95-preview | 51 | 9/6/2026 |
| 0.0.1-alpha.109-preview | 0 | 9/11/2026 |
| 0.0.1-alpha.108-preview | 46 | 9/8/2026 |
| 0.0.1-alpha.107-preview | 48 | 9/8/2026 |
| 0.0.1-alpha.106-preview | 43 | 9/8/2026 |
| 0.0.1-alpha.105-preview | 39 | 9/8/2026 |
| 0.0.1-alpha.104-preview | 59 | 9/7/2026 |
| 0.0.1-alpha.103-preview | 47 | 9/7/2026 |
| 0.0.1-alpha.102-preview | 53 | 9/6/2026 |
| 0.0.1-alpha.101-preview | 120 | 9/6/2026 |
| 0.0.1-alpha.100-preview | 54 | 9/6/2026 |