Skip to content

Commit

Permalink
Remove need for ProcessingFactory in favor of injectible ProcessingSt…
Browse files Browse the repository at this point in the history
…rategy; remove StackExchange code and references
  • Loading branch information
nick-cromwell committed Dec 19, 2020
1 parent 60e6ebc commit a88e84a
Show file tree
Hide file tree
Showing 17 changed files with 31 additions and 256 deletions.
3 changes: 0 additions & 3 deletions src/AspNetCoreRateLimit/AspNetCoreRateLimit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,20 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="StackExchange.Redis" Version="2.2.4" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'netcoreapp3.1'">
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="StackExchange.Redis" Version="2.2.4" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'net5.0'">
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="StackExchange.Redis" Version="2.2.4" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'netcoreapp3.1'">
Expand Down
10 changes: 6 additions & 4 deletions src/AspNetCoreRateLimit/Core/ClientRateLimitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ public class ClientRateLimitProcessor : RateLimitProcessor, IRateLimitProcessor
private readonly ClientRateLimitOptions _options;
private readonly IProcessingStrategy _processingStrategy;
private readonly IRateLimitStore<ClientRateLimitPolicy> _policyStore;
private readonly ICounterKeyBuilder _counterKeyBuilder;

public ClientRateLimitProcessor(
IProcessingStrategyFactory processingStrategyFactory,
ClientRateLimitOptions options,
IRateLimitCounterStore counterStore,
IClientPolicyStore policyStore,
IRateLimitConfiguration config)
IRateLimitConfiguration config,
IProcessingStrategy processingStrategy)
: base(options)
{
_options = options;
_policyStore = policyStore;
_processingStrategy = processingStrategyFactory.CreateProcessingStrategy(counterStore, new ClientCounterKeyBuilder(options), config, options);
_counterKeyBuilder = new ClientCounterKeyBuilder(options);
_processingStrategy = processingStrategy;
}

public async Task<IEnumerable<RateLimitRule>> GetMatchingRulesAsync(ClientRequestIdentity identity, CancellationToken cancellationToken = default)
Expand All @@ -32,7 +34,7 @@ public async Task<IEnumerable<RateLimitRule>> GetMatchingRulesAsync(ClientReques

public async Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default)
{
return await _processingStrategy.ProcessRequestAsync(requestIdentity, rule, cancellationToken);
return await _processingStrategy.ProcessRequestAsync(requestIdentity, rule, _counterKeyBuilder, _options, cancellationToken);
}
}
}
3 changes: 0 additions & 3 deletions src/AspNetCoreRateLimit/Core/IRateLimitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ namespace AspNetCoreRateLimit
public interface IRateLimitProcessor
{
Task<IEnumerable<RateLimitRule>> GetMatchingRulesAsync(ClientRequestIdentity identity, CancellationToken cancellationToken = default);

RateLimitHeaders GetRateLimitHeaders(RateLimitCounter? counter, RateLimitRule rule, CancellationToken cancellationToken = default);

Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default);

bool IsWhitelisted(ClientRequestIdentity requestIdentity);
}
}
10 changes: 6 additions & 4 deletions src/AspNetCoreRateLimit/Core/IpRateLimitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ public class IpRateLimitProcessor : RateLimitProcessor, IRateLimitProcessor
private readonly IpRateLimitOptions _options;
private readonly IRateLimitStore<IpRateLimitPolicies> _policyStore;
private readonly IProcessingStrategy _processingStrategy;
private readonly ICounterKeyBuilder _counterKeyBuilder;

public IpRateLimitProcessor(
IProcessingStrategyFactory processingStrategyFactory,
IpRateLimitOptions options,
IRateLimitCounterStore counterStore,
IIpPolicyStore policyStore,
IRateLimitConfiguration config)
IRateLimitConfiguration config,
IProcessingStrategy processingStrategy)
: base(options)
{
_options = options;
_policyStore = policyStore;
_processingStrategy = processingStrategyFactory.CreateProcessingStrategy(counterStore, new IpCounterKeyBuilder(options), config, options);
_counterKeyBuilder = new IpCounterKeyBuilder(options);
_processingStrategy = processingStrategy;
}


Expand All @@ -47,7 +49,7 @@ public async Task<IEnumerable<RateLimitRule>> GetMatchingRulesAsync(ClientReques

public async Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default)
{
return await _processingStrategy.ProcessRequestAsync(requestIdentity, rule, cancellationToken);
return await _processingStrategy.ProcessRequestAsync(requestIdentity, rule, _counterKeyBuilder, _options, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,28 @@ namespace AspNetCoreRateLimit
{
public class AsyncKeyLockProcessingStrategy : ProcessingStrategy
{
private readonly RateLimitOptions _options;
private readonly IRateLimitCounterStore _counterStore;
private readonly ICounterKeyBuilder _counterKeyBuilder;
private readonly IRateLimitConfiguration _config;

public AsyncKeyLockProcessingStrategy(IRateLimitCounterStore counterStore, ICounterKeyBuilder counterKeyBuilder, IRateLimitConfiguration config, RateLimitOptions options)
: base(counterKeyBuilder, config, options)
public AsyncKeyLockProcessingStrategy(IRateLimitCounterStore counterStore, IRateLimitConfiguration config)
: base(config)
{
_counterStore = counterStore;
_counterKeyBuilder = counterKeyBuilder;
_config = config;
_options = options;
}


/// The key-lock used for limiting requests.
private static readonly AsyncKeyLock AsyncLock = new AsyncKeyLock();

public override async Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default)
public override async Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions, CancellationToken cancellationToken = default)
{
var counter = new RateLimitCounter
{
Timestamp = DateTime.UtcNow,
Count = 1
};

var counterId = BuildCounterKey(requestIdentity, rule);
var counterId = BuildCounterKey(requestIdentity, rule, counterKeyBuilder, rateLimitOptions);

// serial reads and writes on same key
using (await AsyncLock.WriterLockAsync(counterId).ConfigureAwait(false))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace AspNetCoreRateLimit
{
public interface IProcessingStrategy
{
Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default);
Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions, CancellationToken cancellationToken = default);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,20 @@ namespace AspNetCoreRateLimit
{
public abstract class ProcessingStrategy : IProcessingStrategy
{
private readonly RateLimitOptions _options;
private readonly ICounterKeyBuilder _counterKeyBuilder;
private readonly IRateLimitConfiguration _config;

public ProcessingStrategy(ICounterKeyBuilder counterKeyBuilder, IRateLimitConfiguration config, RateLimitOptions options)
: base()
protected ProcessingStrategy(IRateLimitConfiguration config)
{
_counterKeyBuilder = counterKeyBuilder;
_config = config;
_options = options;
}

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

protected virtual string BuildCounterKey(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions)
{
var key = _counterKeyBuilder.Build(requestIdentity, rule);
var key = counterKeyBuilder.Build(requestIdentity, rule);

if (_options.EnableEndpointRateLimiting && _config.EndpointCounterKeyBuilder != null)
if (rateLimitOptions.EnableEndpointRateLimiting && _config.EndpointCounterKeyBuilder != null)
{
key += _config.EndpointCounterKeyBuilder.Build(requestIdentity, rule);
}
Expand All @@ -36,7 +33,5 @@ protected virtual string BuildCounterKey(ClientRequestIdentity requestIdentity,

return Convert.ToBase64String(hash);
}

public abstract Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, CancellationToken cancellationToken = default);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ public class ClientRateLimitMiddleware : RateLimitMiddleware<ClientRateLimitProc
private readonly ILogger<ClientRateLimitMiddleware> _logger;

public ClientRateLimitMiddleware(RequestDelegate next,
IProcessingStrategy processingStrategy,
IOptions<ClientRateLimitOptions> options,
IProcessingStrategyFactory processingStrategyFactory,
IRateLimitCounterStore counterStore,
IClientPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<ClientRateLimitMiddleware> logger)
: base(next, options?.Value, new ClientRateLimitProcessor(processingStrategyFactory, options?.Value, counterStore, policyStore, config), config)
: base(next, options?.Value, new ClientRateLimitProcessor(options?.Value, counterStore, policyStore, config, processingStrategy), config)
{
_logger = logger;
}
Expand Down
8 changes: 4 additions & 4 deletions src/AspNetCoreRateLimit/Middleware/IpRateLimitMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ public class IpRateLimitMiddleware : RateLimitMiddleware<IpRateLimitProcessor>
private readonly ILogger<IpRateLimitMiddleware> _logger;

public IpRateLimitMiddleware(RequestDelegate next,
IProcessingStrategyFactory processingStrategyFactory,
IProcessingStrategy processingStrategy,
IOptions<IpRateLimitOptions> options,
IRateLimitCounterStore counterStore,
IIpPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<IpRateLimitMiddleware> logger)
: base(next, options?.Value, new IpRateLimitProcessor(processingStrategyFactory, options?.Value, counterStore, policyStore, config), config)

ILogger<IpRateLimitMiddleware> logger
)
: base(next, options?.Value, new IpRateLimitProcessor(options?.Value, counterStore, policyStore, config, processingStrategy), config)
{
_logger = logger;
}
Expand Down
12 changes: 2 additions & 10 deletions src/AspNetCoreRateLimit/StartupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static IServiceCollection AddMemoryCacheStores(this IServiceCollection se
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
services.AddSingleton<IProcessingStrategyFactory, ProcessingStrategyFactory>();
services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>();
return services;
}

Expand All @@ -19,15 +19,7 @@ public static IServiceCollection AddDistributedCacheStores(this IServiceCollecti
services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>();
services.AddSingleton<IClientPolicyStore, DistributedCacheClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>();
return services;
}

public static IServiceCollection AddStackExchangeRedisStores(this IServiceCollection services)
{
services.AddSingleton<IProcessingStrategyFactory, ProcessingStrategyFactory>();
services.AddSingleton<IIpPolicyStore, StackExchangeRedisIpPolicyStore>();
services.AddSingleton<IClientPolicyStore, StackExchangeRedisClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, StackExchangeRedisRateLimitCounterStore>();
services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>();
return services;
}

Expand Down

This file was deleted.

Loading

0 comments on commit a88e84a

Please sign in to comment.