Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="StackExchange.Redis" Version="2.6.104" />
<PackageReference Include="StackExchange.Redis" Version="2.8.0" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release'">
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
Expand All @@ -31,7 +31,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>

<PropertyGroup Condition="'$(APPVEYOR)' == 'true'">
Expand Down
12 changes: 7 additions & 5 deletions src/AspNetCoreRateLimit/AspNetCoreRateLimit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>
<NoWarn>IDE0130</NoWarn>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AsyncKeyedLock" Version="6.2.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.3" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageReference Include="AsyncKeyedLock" Version="7.1.3" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

Expand All @@ -33,7 +35,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>

<PropertyGroup Condition="'$(APPVEYOR)' == 'true'">
Expand Down
25 changes: 8 additions & 17 deletions src/AspNetCoreRateLimit/Core/ClientRateLimitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,15 @@

namespace AspNetCoreRateLimit
{
public class ClientRateLimitProcessor : RateLimitProcessor, IRateLimitProcessor
public class ClientRateLimitProcessor(
ClientRateLimitOptions options,
IClientPolicyStore policyStore,
IProcessingStrategy processingStrategy) : RateLimitProcessor(options), IRateLimitProcessor
{
private readonly ClientRateLimitOptions _options;
private readonly IProcessingStrategy _processingStrategy;
private readonly IRateLimitStore<ClientRateLimitPolicy> _policyStore;
private readonly ICounterKeyBuilder _counterKeyBuilder;

public ClientRateLimitProcessor(
ClientRateLimitOptions options,
IClientPolicyStore policyStore,
IProcessingStrategy processingStrategy)
: base(options)
{
_options = options;
_policyStore = policyStore;
_counterKeyBuilder = new ClientCounterKeyBuilder(options);
_processingStrategy = processingStrategy;
}
private readonly ClientRateLimitOptions _options = options;
private readonly IProcessingStrategy _processingStrategy = processingStrategy;
private readonly IRateLimitStore<ClientRateLimitPolicy> _policyStore = policyStore;
private readonly ICounterKeyBuilder _counterKeyBuilder = new ClientCounterKeyBuilder(options);

public async Task<IEnumerable<RateLimitRule>> GetMatchingRulesAsync(ClientRequestIdentity identity, CancellationToken cancellationToken = default)
{
Expand Down
4 changes: 2 additions & 2 deletions src/AspNetCoreRateLimit/Core/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static bool IsRegexMatch(this string source, string value)
}
// if the regex is e.g. /api/values/ the path should be an exact match
// if all paths below this should be included the regex should be /api/values/*
if (value[value.Length - 1] != '$')
if (value[^1] != '$')
{
value += '$';
}
Expand All @@ -49,7 +49,7 @@ public static string RetryAfterFrom(this DateTime timestamp, RateLimitRule rule)
public static TimeSpan ToTimeSpan(this string timeSpan)
{
var l = timeSpan.Length - 1;
var value = timeSpan.Substring(0, l);
var value = timeSpan[..l];
var type = timeSpan.Substring(l, 1);

return type switch
Expand Down
26 changes: 8 additions & 18 deletions src/AspNetCoreRateLimit/Core/IpRateLimitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,15 @@

namespace AspNetCoreRateLimit
{
public class IpRateLimitProcessor : RateLimitProcessor, IRateLimitProcessor
public class IpRateLimitProcessor(
IpRateLimitOptions options,
IIpPolicyStore policyStore,
IProcessingStrategy processingStrategy) : RateLimitProcessor(options), IRateLimitProcessor
{
private readonly IpRateLimitOptions _options;
private readonly IRateLimitStore<IpRateLimitPolicies> _policyStore;
private readonly IProcessingStrategy _processingStrategy;
private readonly ICounterKeyBuilder _counterKeyBuilder;

public IpRateLimitProcessor(
IpRateLimitOptions options,
IIpPolicyStore policyStore,
IProcessingStrategy processingStrategy)
: base(options)
{
_options = options;
_policyStore = policyStore;
_counterKeyBuilder = new IpCounterKeyBuilder(options);
_processingStrategy = processingStrategy;
}

private readonly IpRateLimitOptions _options = options;
private readonly IRateLimitStore<IpRateLimitPolicies> _policyStore = policyStore;
private readonly IProcessingStrategy _processingStrategy = processingStrategy;
private readonly ICounterKeyBuilder _counterKeyBuilder = new IpCounterKeyBuilder(options);

public async Task<IEnumerable<RateLimitRule>> GetMatchingRulesAsync(ClientRequestIdentity identity, CancellationToken cancellationToken = default)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,10 @@

namespace AspNetCoreRateLimit
{
public class AsyncKeyLockProcessingStrategy : ProcessingStrategy
public class AsyncKeyLockProcessingStrategy(IRateLimitCounterStore counterStore, IRateLimitConfiguration config) : ProcessingStrategy(config)
{
private readonly IRateLimitCounterStore _counterStore;
private readonly IRateLimitConfiguration _config;

public AsyncKeyLockProcessingStrategy(IRateLimitCounterStore counterStore, IRateLimitConfiguration config)
: base(config)
{
_counterStore = counterStore;
_config = config;
}
private readonly IRateLimitCounterStore _counterStore = counterStore;
private readonly IRateLimitConfiguration _config = config;

/// The key-lock used for limiting requests.
private static readonly AsyncKeyedLocker<string> AsyncLock = new(o =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@

namespace AspNetCoreRateLimit
{
public abstract class ProcessingStrategy : IProcessingStrategy
public abstract class ProcessingStrategy(IRateLimitConfiguration config) : IProcessingStrategy
{
private readonly IRateLimitConfiguration _config;

protected ProcessingStrategy(IRateLimitConfiguration config)
{
_config = config;
}
private readonly IRateLimitConfiguration _config = config;

public abstract Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions, CancellationToken cancellationToken = default);

Expand Down
12 changes: 3 additions & 9 deletions src/AspNetCoreRateLimit/Core/RateLimitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,9 @@

namespace AspNetCoreRateLimit
{
public abstract class RateLimitProcessor
public abstract class RateLimitProcessor(RateLimitOptions options)
{
private readonly RateLimitOptions _options;

protected RateLimitProcessor(RateLimitOptions options)
{
_options = options;
}

private readonly RateLimitOptions _options = options;

public virtual bool IsWhitelisted(ClientRequestIdentity requestIdentity)
{
Expand Down Expand Up @@ -143,7 +137,7 @@ protected virtual List<RateLimitRule> GetMatchingRules(ClientRequestIdentity ide
}
}

limits = limits.OrderBy(l => l.PeriodTimespan).ToList();
limits = [.. limits.OrderBy(l => l.PeriodTimespan)];

if (_options.StackBlockedRequests)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
namespace AspNetCoreRateLimit
{
public class ClientCounterKeyBuilder : ICounterKeyBuilder
public class ClientCounterKeyBuilder(ClientRateLimitOptions options) : ICounterKeyBuilder
{
private readonly ClientRateLimitOptions _options;

public ClientCounterKeyBuilder(ClientRateLimitOptions options)
{
_options = options;
}
private readonly ClientRateLimitOptions _options = options;

public string Build(ClientRequestIdentity requestIdentity, RateLimitRule rule)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
namespace AspNetCoreRateLimit
{
public class IpCounterKeyBuilder : ICounterKeyBuilder
public class IpCounterKeyBuilder(IpRateLimitOptions options) : ICounterKeyBuilder
{
private readonly IpRateLimitOptions _options;

public IpCounterKeyBuilder(IpRateLimitOptions options)
{
_options = options;
}
private readonly IpRateLimitOptions _options = options;

public string Build(ClientRequestIdentity requestIdentity, RateLimitRule rule)
{
Expand Down
20 changes: 7 additions & 13 deletions src/AspNetCoreRateLimit/Middleware/ClientRateLimitMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@

namespace AspNetCoreRateLimit
{
public class ClientRateLimitMiddleware : RateLimitMiddleware<ClientRateLimitProcessor>
public class ClientRateLimitMiddleware(RequestDelegate next,
IProcessingStrategy processingStrategy,
IOptions<ClientRateLimitOptions> options,
IClientPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<ClientRateLimitMiddleware> logger) : RateLimitMiddleware<ClientRateLimitProcessor>(next, options?.Value, new ClientRateLimitProcessor(options?.Value, policyStore, processingStrategy), config)
{
private readonly ILogger<ClientRateLimitMiddleware> _logger;

public ClientRateLimitMiddleware(RequestDelegate next,
IProcessingStrategy processingStrategy,
IOptions<ClientRateLimitOptions> options,
IClientPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<ClientRateLimitMiddleware> logger)
: base(next, options?.Value, new ClientRateLimitProcessor(options?.Value, policyStore, processingStrategy), config)
{
_logger = logger;
}
private readonly ILogger<ClientRateLimitMiddleware> _logger = logger;

protected override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
{
Expand Down
22 changes: 8 additions & 14 deletions src/AspNetCoreRateLimit/Middleware/IpRateLimitMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@

namespace AspNetCoreRateLimit
{
public class IpRateLimitMiddleware : RateLimitMiddleware<IpRateLimitProcessor>
public class IpRateLimitMiddleware(RequestDelegate next,
IProcessingStrategy processingStrategy,
IOptions<IpRateLimitOptions> options,
IIpPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<IpRateLimitMiddleware> logger
) : RateLimitMiddleware<IpRateLimitProcessor>(next, options?.Value, new IpRateLimitProcessor(options?.Value, policyStore, processingStrategy), config)
{
private readonly ILogger<IpRateLimitMiddleware> _logger;

public IpRateLimitMiddleware(RequestDelegate next,
IProcessingStrategy processingStrategy,
IOptions<IpRateLimitOptions> options,
IIpPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<IpRateLimitMiddleware> logger
)
: base(next, options?.Value, new IpRateLimitProcessor(options?.Value, policyStore, processingStrategy), config)
{
_logger = logger;
}
private readonly ILogger<IpRateLimitMiddleware> _logger = logger;

protected override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
{
Expand Down
20 changes: 7 additions & 13 deletions src/AspNetCoreRateLimit/Middleware/RateLimitConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@

namespace AspNetCoreRateLimit
{
public class RateLimitConfiguration : IRateLimitConfiguration
public class RateLimitConfiguration(
IOptions<IpRateLimitOptions> ipOptions,
IOptions<ClientRateLimitOptions> clientOptions) : IRateLimitConfiguration
{
public IList<IClientResolveContributor> ClientResolvers { get; } = new List<IClientResolveContributor>();
public IList<IIpResolveContributor> IpResolvers { get; } = new List<IIpResolveContributor>();
public IList<IClientResolveContributor> ClientResolvers { get; } = [];
public IList<IIpResolveContributor> IpResolvers { get; } = [];

public virtual ICounterKeyBuilder EndpointCounterKeyBuilder { get; } = new PathCounterKeyBuilder();

public virtual Func<double> RateIncrementer { get; } = () => 1;

public RateLimitConfiguration(
IOptions<IpRateLimitOptions> ipOptions,
IOptions<ClientRateLimitOptions> clientOptions)
{
IpRateLimitOptions = ipOptions?.Value;
ClientRateLimitOptions = clientOptions?.Value;
}

protected readonly IpRateLimitOptions IpRateLimitOptions;
protected readonly ClientRateLimitOptions ClientRateLimitOptions;
protected readonly IpRateLimitOptions IpRateLimitOptions = ipOptions?.Value;
protected readonly ClientRateLimitOptions ClientRateLimitOptions = clientOptions?.Value;

public virtual void RegisterResolvers()
{
Expand Down
2 changes: 1 addition & 1 deletion src/AspNetCoreRateLimit/Models/IpRateLimitPolicies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace AspNetCoreRateLimit
{
public class IpRateLimitPolicies
{
public List<IpRateLimitPolicy> IpRules { get; set; } = new List<IpRateLimitPolicy>();
public List<IpRateLimitPolicy> IpRules { get; set; } = [];
}
}
2 changes: 1 addition & 1 deletion src/AspNetCoreRateLimit/Models/RateLimitPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace AspNetCoreRateLimit
{
public class RateLimitPolicy
{
public List<RateLimitRule> Rules { get; set; } = new List<RateLimitRule>();
public List<RateLimitRule> Rules { get; set; } = [];
}
}
1 change: 0 additions & 1 deletion src/AspNetCoreRateLimit/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@

namespace AspNetCoreRateLimit
{
public class ClientHeaderResolveContributor : IClientResolveContributor
public class ClientHeaderResolveContributor(string headerName) : IClientResolveContributor
{
private readonly string _headerName;
private readonly string _headerName = headerName;

public ClientHeaderResolveContributor(string headerName)
{
_headerName = headerName;
}
public Task<string> ResolveClientAsync(HttpContext httpContext)
{
string clientId = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ namespace AspNetCoreRateLimit
{
public class IpConnectionResolveContributor : IIpResolveContributor
{

public IpConnectionResolveContributor()
{

}

public string ResolveIp(HttpContext httpContext)
{
return httpContext.Connection.RemoteIpAddress?.ToString();
Expand Down
11 changes: 3 additions & 8 deletions src/AspNetCoreRateLimit/Resolvers/IpHeaderResolveContributor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@

namespace AspNetCoreRateLimit
{
public class IpHeaderResolveContributor : IIpResolveContributor
public class IpHeaderResolveContributor(
string headerName) : IIpResolveContributor
{
private readonly string _headerName;

public IpHeaderResolveContributor(
string headerName)
{
_headerName = headerName;
}
private readonly string _headerName = headerName;

public string ResolveIp(HttpContext httpContext)
{
Expand Down
Loading