39 lines
1.3 KiB
C#
39 lines
1.3 KiB
C#
using Microsoft.AspNetCore.RateLimiting;
|
|||
|
|
|
||
|
|
using PrivaPub.Federation.Objects;
|
||
|
|
using PrivaPub.Federation.Signing;
|
||
|
|
|
||
|
|
using System.Threading.RateLimiting;
|
||
|
|
|
||
|
|
namespace PrivaPub.Infrastructure
|
||
|
|
{
|
||
|
|
public static class RateLimiting
|
||
|
|
{
|
||
|
|
public const string Accounts = "accounts";
|
||
|
|
public const string Inbox = "inbox";
|
||
|
|
|
||
|
|
public static IServiceCollection PrivaPubRateLimiting(this IServiceCollection service) =>
|
||
|
|
service.AddRateLimiter(options =>
|
||
|
|
{
|
||
|
|
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||
|
|
options.AddPolicy(Accounts, context => RateLimitPartition.GetFixedWindowLimiter(
|
||
|
|
context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
|
||
|
|
_ => new FixedWindowRateLimiterOptions { PermitLimit = 10, Window = TimeSpan.FromMinutes(1), QueueLimit = 0 }));
|
||
|
|
options.AddPolicy(Inbox, context => RateLimitPartition.GetTokenBucketLimiter(
|
||
|
|
SenderOrigin(context.Request) ?? "unsigned:" + context.Connection.RemoteIpAddress,
|
||
|
|
_ => new TokenBucketRateLimiterOptions
|
||
|
|
{
|
||
|
|
TokenLimit = 300,
|
||
|
|
TokensPerPeriod = 50,
|
||
|
|
ReplenishmentPeriod = TimeSpan.FromSeconds(10),
|
||
|
|
QueueLimit = 0
|
||
|
|
}));
|
||
|
|
});
|
||
|
|
|
||
|
|
static string SenderOrigin(HttpRequest request)
|
||
|
|
{
|
||
|
|
var signature = request.Headers["Signature"].ToString();
|
||
|
|
return string.IsNullOrEmpty(signature) ? default : Origin.Of(HttpSignatures.Parse(signature)?.KeyId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|