#372 use period timespan to decide when client can make requests again (#404)

This commit is contained in:
Tom Pallister 2018-06-15 20:29:49 +01:00 committed by GitHub
parent 87c13bd9b4
commit 9979f8a4b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 429 additions and 359 deletions

View File

@ -19,7 +19,7 @@ OK so to get rate limiting working for a ReRoute you need to add the following j
ClientWhitelist - This is an array that contains the whitelist of the client. It means that the client in this array will not be affected by the rate limiting. ClientWhitelist - This is an array that contains the whitelist of the client. It means that the client in this array will not be affected by the rate limiting.
EnableRateLimiting - This value specifies enable endpoint rate limiting. EnableRateLimiting - This value specifies enable endpoint rate limiting.
Period - This value specifies the period, such as 1s, 5m, 1h,1d and so on. Period - This value specifies the period that the limit applies to, such as 1s, 5m, 1h,1d and so on. If you make more requests in the period than the limit allows then you need to wait for PeriodTimespan to elapse before you make another request.
PeriodTimespan - This value specifies that we can retry after a certain number of seconds. PeriodTimespan - This value specifies that we can retry after a certain number of seconds.
Limit - This value specifies the maximum number of requests that a client can make in a defined period. Limit - This value specifies the maximum number of requests that a client can make in a defined period.

View File

@ -34,7 +34,7 @@ namespace Ocelot.RateLimit
if (entry.HasValue) if (entry.HasValue)
{ {
// entry has not expired // entry has not expired
if (entry.Value.Timestamp + ConvertToTimeSpan(rule.Period) >= DateTime.UtcNow) if (entry.Value.Timestamp + TimeSpan.FromSeconds(rule.PeriodTimespan) >= DateTime.UtcNow)
{ {
// increment request count // increment request count
var totalRequests = entry.Value.TotalRequests + 1; var totalRequests = entry.Value.TotalRequests + 1;

View File

@ -90,6 +90,71 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_wait_for_period_timespan_to_elapse_before_making_next_request()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/api/ClientRateLimit",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51926,
}
},
DownstreamScheme = "http",
UpstreamPathTemplate = "/api/ClientRateLimit",
UpstreamHttpMethod = new List<string> { "Get" },
RequestIdKey = _steps.RequestIdKey,
RateLimitOptions = new FileRateLimitRule()
{
EnableRateLimiting = true,
ClientWhitelist = new List<string>(),
Limit = 3,
Period = "1s",
PeriodTimespan = 2
}
}
},
GlobalConfiguration = new FileGlobalConfiguration()
{
RateLimitOptions = new FileRateLimitOptions()
{
ClientIdHeader = "ClientId",
DisableRateLimitHeaders = false,
QuotaExceededMessage = "",
RateLimitCounterPrefix = "",
HttpStatusCode = 428
},
RequestIdKey ="oceclientrequest"
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51926", "/api/ClientRateLimit"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
.Then(x => _steps.ThenTheStatusCodeShouldBe(200))
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit", 2))
.Then(x => _steps.ThenTheStatusCodeShouldBe(200))
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
.Then(x => _steps.ThenTheStatusCodeShouldBe(428))
.And(x => _steps.GivenIWait(1000))
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
.Then(x => _steps.ThenTheStatusCodeShouldBe(428))
.And(x => _steps.GivenIWait(1000))
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
.Then(x => _steps.ThenTheStatusCodeShouldBe(200))
.BDDfy();
}
[Fact] [Fact]
public void should_call_middleware_withWhitelistClient() public void should_call_middleware_withWhitelistClient()
{ {

View File

@ -183,6 +183,11 @@ namespace Ocelot.AcceptanceTests
_ocelotClient = _ocelotServer.CreateClient(); _ocelotClient = _ocelotServer.CreateClient();
} }
internal void GivenIWait(int wait)
{
Thread.Sleep(wait);
}
public void GivenOcelotIsRunningWithMiddleareBeforePipeline<T>(Func<object, Task> callback) public void GivenOcelotIsRunningWithMiddleareBeforePipeline<T>(Func<object, Task> callback)
{ {
_webHostBuilder = new WebHostBuilder(); _webHostBuilder = new WebHostBuilder();