177 lines
5.3 KiB
C#
177 lines
5.3 KiB
C#
#define FIRST // FIRST SECOND
|
|
#if NEVER
|
|
#elif FIRST
|
|
// <snippet_1>
|
|
using Microsoft.AspNetCore.RateLimiting;
|
|
using System.Threading.RateLimiting;
|
|
using WebRateLimitAuth.Models;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
builder.Services.AddRazorPages();
|
|
builder.Services.AddControllersWithViews();
|
|
|
|
builder.Services.Configure<MyRateLimitOptions>(
|
|
builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit));
|
|
|
|
var myOptions = new MyRateLimitOptions();
|
|
builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions);
|
|
var fixedPolicy = "fixed";
|
|
|
|
builder.Services.AddRateLimiter(_ => _
|
|
.AddFixedWindowLimiter(policyName: fixedPolicy, options =>
|
|
{
|
|
options.PermitLimit = myOptions.PermitLimit;
|
|
options.Window = TimeSpan.FromSeconds(myOptions.Window);
|
|
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
|
|
options.QueueLimit = myOptions.QueueLimit;
|
|
}));
|
|
|
|
var slidingPolicy = "sliding";
|
|
|
|
builder.Services.AddRateLimiter(_ => _
|
|
.AddSlidingWindowLimiter(policyName: slidingPolicy, options =>
|
|
{
|
|
options.PermitLimit = myOptions.SlidingPermitLimit;
|
|
options.Window = TimeSpan.FromSeconds(myOptions.Window);
|
|
options.SegmentsPerWindow = myOptions.SegmentsPerWindow;
|
|
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
|
|
options.QueueLimit = myOptions.QueueLimit;
|
|
}));
|
|
|
|
var app = builder.Build();
|
|
app.UseRateLimiter();
|
|
|
|
if (!app.Environment.IsDevelopment())
|
|
{
|
|
app.UseExceptionHandler("/Error");
|
|
app.UseHsts();
|
|
}
|
|
|
|
app.UseHttpsRedirection();
|
|
app.UseStaticFiles();
|
|
|
|
app.MapRazorPages().RequireRateLimiting(slidingPolicy);
|
|
app.MapDefaultControllerRoute().RequireRateLimiting(fixedPolicy);
|
|
|
|
app.Run();
|
|
// </snippet_1>
|
|
#elif SECOND
|
|
// <snippet_2>
|
|
using Microsoft.AspNetCore.RateLimiting;
|
|
using System.Threading.RateLimiting;
|
|
using WebRateLimitAuth.Models;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
builder.Services.AddRazorPages();
|
|
builder.Services.AddControllersWithViews();
|
|
|
|
builder.Services.Configure<MyRateLimitOptions>(
|
|
builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit));
|
|
|
|
var myOptions = new MyRateLimitOptions();
|
|
builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions);
|
|
var fixedPolicy = "fixed";
|
|
|
|
builder.Services.AddRateLimiter(_ => _
|
|
.AddFixedWindowLimiter(policyName: fixedPolicy, options =>
|
|
{
|
|
options.PermitLimit = myOptions.PermitLimit;
|
|
options.Window = TimeSpan.FromSeconds(myOptions.Window);
|
|
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
|
|
options.QueueLimit = myOptions.QueueLimit;
|
|
}));
|
|
|
|
var slidingPolicy = "sliding";
|
|
|
|
builder.Services.AddRateLimiter(_ => _
|
|
.AddSlidingWindowLimiter(policyName: slidingPolicy, options =>
|
|
{
|
|
options.PermitLimit = myOptions.SlidingPermitLimit;
|
|
options.Window = TimeSpan.FromSeconds(myOptions.Window);
|
|
options.SegmentsPerWindow = myOptions.SegmentsPerWindow;
|
|
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
|
|
options.QueueLimit = myOptions.QueueLimit;
|
|
}));
|
|
|
|
var app = builder.Build();
|
|
|
|
app.UseRateLimiter();
|
|
|
|
if (!app.Environment.IsDevelopment())
|
|
{
|
|
app.UseExceptionHandler("/Error");
|
|
app.UseHsts();
|
|
}
|
|
|
|
app.UseHttpsRedirection();
|
|
app.UseStaticFiles();
|
|
|
|
app.MapRazorPages();
|
|
app.MapDefaultControllerRoute();
|
|
|
|
app.Run();
|
|
// </snippet_2>
|
|
#elif CHAINED
|
|
// <snippet_3>
|
|
using System.Globalization;
|
|
using System.Threading.RateLimiting;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
builder.Services.AddRateLimiter(_ =>
|
|
{
|
|
_.OnRejected = (context, _) =>
|
|
{
|
|
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
|
|
{
|
|
context.HttpContext.Response.Headers.RetryAfter =
|
|
((int) retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
|
|
}
|
|
|
|
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
|
|
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
|
|
|
|
return new ValueTask();
|
|
};
|
|
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
|
|
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
|
{
|
|
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
|
|
|
return RateLimitPartition.GetFixedWindowLimiter
|
|
(userAgent, _ =>
|
|
new FixedWindowRateLimiterOptions
|
|
{
|
|
AutoReplenishment = true,
|
|
PermitLimit = 4,
|
|
Window = TimeSpan.FromSeconds(2)
|
|
});
|
|
}),
|
|
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
|
{
|
|
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
|
|
|
return RateLimitPartition.GetFixedWindowLimiter
|
|
(userAgent, _ =>
|
|
new FixedWindowRateLimiterOptions
|
|
{
|
|
AutoReplenishment = true,
|
|
PermitLimit = 20,
|
|
Window = TimeSpan.FromSeconds(30)
|
|
});
|
|
}));
|
|
});
|
|
|
|
var app = builder.Build();
|
|
app.UseRateLimiter();
|
|
|
|
static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000");
|
|
|
|
app.MapGet("/", () => Results.Ok($"Hello {GetTicks()}"));
|
|
|
|
app.Run();
|
|
// </snippet_3>
|
|
#endif
|