-
Notifications
You must be signed in to change notification settings - Fork 447
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #180 from rangerlabs/master
Allow a Processing Strategy to be injected and configured via new startup extension methods
- Loading branch information
Showing
21 changed files
with
199 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
src/AspNetCoreRateLimit/Core/ProcessingStrategies/AsyncKeyLockProcessingStrategy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace AspNetCoreRateLimit | ||
{ | ||
public class AsyncKeyLockProcessingStrategy : ProcessingStrategy | ||
{ | ||
private readonly IRateLimitCounterStore _counterStore; | ||
private readonly IRateLimitConfiguration _config; | ||
|
||
public AsyncKeyLockProcessingStrategy(IRateLimitCounterStore counterStore, IRateLimitConfiguration config) | ||
: base(config) | ||
{ | ||
_counterStore = counterStore; | ||
_config = config; | ||
} | ||
|
||
/// The key-lock used for limiting requests. | ||
private static readonly AsyncKeyLock AsyncLock = new AsyncKeyLock(); | ||
|
||
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, counterKeyBuilder, rateLimitOptions); | ||
|
||
// serial reads and writes on same key | ||
using (await AsyncLock.WriterLockAsync(counterId).ConfigureAwait(false)) | ||
{ | ||
var entry = await _counterStore.GetAsync(counterId, cancellationToken); | ||
|
||
if (entry.HasValue) | ||
{ | ||
// entry has not expired | ||
if (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow) | ||
{ | ||
// increment request count | ||
var totalCount = entry.Value.Count + _config.RateIncrementer?.Invoke() ?? 1; | ||
|
||
// deep copy | ||
counter = new RateLimitCounter | ||
{ | ||
Timestamp = entry.Value.Timestamp, | ||
Count = totalCount | ||
}; | ||
} | ||
} | ||
|
||
// stores: id (string) - timestamp (datetime) - total_requests (long) | ||
await _counterStore.SetAsync(counterId, counter, rule.PeriodTimespan.Value, cancellationToken); | ||
} | ||
|
||
return counter; | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/AspNetCoreRateLimit/Core/ProcessingStrategies/IProcessingStrategy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace AspNetCoreRateLimit | ||
{ | ||
public interface IProcessingStrategy | ||
{ | ||
Task<RateLimitCounter> ProcessRequestAsync(ClientRequestIdentity requestIdentity, RateLimitRule rule, ICounterKeyBuilder counterKeyBuilder, RateLimitOptions rateLimitOptions, CancellationToken cancellationToken = default); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
src/AspNetCoreRateLimit/Core/ProcessingStrategies/ProcessingStrategy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace AspNetCoreRateLimit | ||
{ | ||
public abstract class ProcessingStrategy : IProcessingStrategy | ||
{ | ||
private readonly IRateLimitConfiguration _config; | ||
|
||
protected ProcessingStrategy(IRateLimitConfiguration config) | ||
{ | ||
_config = config; | ||
} | ||
|
||
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); | ||
|
||
if (rateLimitOptions.EnableEndpointRateLimiting && _config.EndpointCounterKeyBuilder != null) | ||
{ | ||
key += _config.EndpointCounterKeyBuilder.Build(requestIdentity, rule); | ||
} | ||
|
||
var bytes = Encoding.UTF8.GetBytes(key); | ||
|
||
using var algorithm = new SHA1Managed(); | ||
var hash = algorithm.ComputeHash(bytes); | ||
|
||
return Convert.ToBase64String(hash); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 0 additions & 17 deletions
17
src/AspNetCoreRateLimit/Middleware/MiddlewareExtensions.cs
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.