public bool Verify(string token, DateTime requestDate, RateLimitSettingsConfig rateLimitSettingsConfig) { var clientRepository = new ClientRepository(); var requestsPerTimeSpanRateLimiter = new TokenBucketRateLimiter(); var timeSpanPassedSinceLastCallRateLimiter = new TimespanPassedSinceLastCallRateLimiter(); var rateLimiterAlgorithm = new RateLimiterAlgorithm(requestsPerTimeSpanRateLimiter, timeSpanPassedSinceLastCallRateLimiter); var rateLimiter = new RateLimiter(clientRepository, rateLimiterAlgorithm); return(rateLimiter.Verify(token, requestDate, rateLimitSettingsConfig)); }
public void Setup() { defaultSettingsConfig = new RateLimitSettingsConfig(); defaultSettingsConfig[RateLimitType.RequestsPerTimespan] = new TokenBucketSettings() { MaxAmount = 5, RefillAmount = 5, RefillTime = 60 }; defaultSettingsConfig[RateLimitType.TimespanPassedSinceLastCall] = new TimespanPassedSinceLastCallSettings() { TimespanLimit = new TimeSpan(0, 1, 0) }; }
public void Evaluate_GetsExpectedConfigSettings_ForGlobalResourceRule() { // arrange var resource = "/api/resource1"; var serverIP = "172.39.67.32"; var resourceRule = new ResourceRule("/api/resource1 : all regions : requests per timespan : default settings", resource, Region.All, RateLimitType.RequestsPerTimespan, RateLimitLevel.Default); var regionRule = new RegionRule("US", RateLimitType.TimespanPassedSinceLastCall, RateLimitLevel.Low); var expected = new RateLimitSettingsConfig(); expected[RateLimitType.RequestsPerTimespan] = new TokenBucketSettings() { MaxAmount = 5, RefillAmount = 5, RefillTime = 60 }; var expectedSettings = (TokenBucketSettings)expected[RateLimitType.RequestsPerTimespan]; var fakeRepository = Substitute.For <IRuleRepository>(); var fakeCache = Substitute.For <IRuleCache>(); fakeCache["/api/resource1All"].Returns(resourceRule); fakeCache["US"].Returns(regionRule); var rulesEngine = new RulesEngine(fakeRepository, fakeCache); // act var result = rulesEngine.Evaluate(resource, serverIP); var resultSettings = (TokenBucketSettings)result[RateLimitType.RequestsPerTimespan]; // assert Assert.AreEqual(resultSettings.MaxAmount, expectedSettings.MaxAmount); Assert.AreEqual(resultSettings.RefillAmount, expectedSettings.RefillAmount); Assert.AreEqual(resultSettings.RefillTime, expectedSettings.RefillTime); }
public bool Verify(string token, DateTime requestDate, RateLimitSettingsConfig rateLimitSettingsConfig) { var isAllowed = true; ClientRequestData clientData = new ClientRequestData(-1, DateTime.MinValue); // check requests per timespan rule if (rateLimitSettingsConfig[RateLimitType.RequestsPerTimespan] != null) { var rateLimitSettings = (TokenBucketSettings)rateLimitSettingsConfig[RateLimitType.RequestsPerTimespan]; clientData = this.clientRepository.GetClientData(token); isAllowed = this.rateLimiterAlgorithm.VerifyRequestsPerTimeSpan(clientData.Count, rateLimitSettings.MaxAmount, rateLimitSettings.RefillAmount, rateLimitSettings.RefillTime, requestDate, clientData.LastUpdateDate); } if (!isAllowed) { return(false); } // check timespan passed if (rateLimitSettingsConfig[RateLimitType.TimespanPassedSinceLastCall] != null) { var rateLimitSettings = (TimespanPassedSinceLastCallSettings)rateLimitSettingsConfig[RateLimitType.TimespanPassedSinceLastCall]; if (clientData.Count == -1) { clientData = this.clientRepository.GetClientData(token); } isAllowed = this.rateLimiterAlgorithm.VerifyTimespanPassedSinceLastCall(requestDate, rateLimitSettings.TimespanLimit, clientData.LastUpdateDate); } if (!isAllowed) { return(false); } // update client data clientData.LastUpdateDate = DateTime.Now; this.clientRepository.AddOrUpdate(token, clientData); return(true); }
public bool Verify(string token, DateTime requestDate, RateLimitSettingsConfig rateLimitSettings = null) { return(this.rateLimiterProxy.Verify(token, requestDate, rateLimitSettings)); }
public RateLimitSettingsConfig Evaluate(string resource, string IPAddress) { Region region = GetRegionFromIPGeoLocationService(IPAddress); // lookup rule in cache in order of rule specificity (most specific to least specific) Rule rule; // 1. resource + region rule rule = (ResourceRule)this.ruleCache[resource + region.ToString()]; // 2. global resource rule if (rule == null) { rule = (ResourceRule)this.ruleCache[resource + Region.All.ToString()]; } else { // 3. region rule rule = (RegionRule)this.ruleCache[region.ToString()]; } // if no rules apply, return default settings if (rule == null) { return(new DefaultRateLimiterSettings().RateLimiterSettings); } else { // populate rate limit settings RateLimitSettingsConfig rateLimitSettingsConfig = new RateLimitSettingsConfig(); switch (rule.RateLimitLevel) { case RateLimitLevel.Low: rateLimitSettingsConfig[RateLimitType.RequestsPerTimespan] = new TokenBucketSettings() { MaxAmount = 1, RefillAmount = 1, RefillTime = 60 }; rateLimitSettingsConfig[RateLimitType.TimespanPassedSinceLastCall] = new TimespanPassedSinceLastCallSettings() { TimespanLimit = new TimeSpan(0, 30, 0) }; break; case RateLimitLevel.Default: rateLimitSettingsConfig[RateLimitType.RequestsPerTimespan] = new TokenBucketSettings() { MaxAmount = 5, RefillAmount = 5, RefillTime = 60 }; rateLimitSettingsConfig[RateLimitType.TimespanPassedSinceLastCall] = new TimespanPassedSinceLastCallSettings() { TimespanLimit = new TimeSpan(0, 30, 0) }; break; case RateLimitLevel.High: rateLimitSettingsConfig[RateLimitType.RequestsPerTimespan] = new TokenBucketSettings() { MaxAmount = 20, RefillAmount = 10, RefillTime = 30 }; rateLimitSettingsConfig[RateLimitType.TimespanPassedSinceLastCall] = new TimespanPassedSinceLastCallSettings() { TimespanLimit = new TimeSpan(0, 0, 30) }; break; } return(rateLimitSettingsConfig); } }