public void OnEvent(HttpContextBase context) { HttpRequestBase request = context.Request; HttpResponseBase response = context.Response; // get policy from repo if (policyRepository != null) { policy = policyRepository.FirstOrDefault(ThrottleManager.GetPolicyKey()); } if (policy == null || (!policy.IpThrottling && !policy.ClientThrottling && !policy.EndpointThrottling)) { response.StatusCode = (int)HttpStatusCode.OK; return; } core.Repository = Repository; core.Policy = policy; var identity = SetIdentity(request); if (core.IsWhitelisted(identity)) { response.StatusCode = (int)HttpStatusCode.OK; return; } if (policy.Endpoints != null && policy.Endpoints.Count > 0) { if (!core.IsEndpointMonitored(identity)) { response.StatusCode = (int)HttpStatusCode.OK; return; } } TimeSpan timeSpan = TimeSpan.FromSeconds(1); // get default rates var defRates = core.RatesWithDefaults(Policy.Rates.ToList()); if (Policy.StackBlockedRequests) { // all requests including the rejected ones will stack in this order: week, day, hour, min, sec // if a client hits the hour limit then the minutes and seconds counters will expire and will eventually get erased from cache defRates.Reverse(); } // apply policy foreach (var rate in defRates) { var rateLimitPeriod = rate.Key; var rateLimit = rate.Value; timeSpan = core.GetTimeSpanFromPeriod(rateLimitPeriod); // apply global rules core.ApplyRules(identity, timeSpan, rateLimitPeriod, ref rateLimit); if (rateLimit > 0) { // increment counter var requestId = ComputeThrottleKey(identity, rateLimitPeriod); var throttleCounter = core.ProcessRequest(timeSpan, requestId); // check if key expired if (throttleCounter.Timestamp + timeSpan < DateTime.UtcNow) { continue; } // check if limit is reached if (throttleCounter.TotalRequests > rateLimit) { // log blocked request if (Logger != null) { Logger.Log(core.ComputeLogEntry(requestId, identity, throttleCounter, rateLimitPeriod.ToString(), rateLimit, request)); } var message = !string.IsNullOrEmpty(this.QuotaExceededMessage) ? this.QuotaExceededMessage : "API calls quota exceeded! maximum admitted {0} per {1}."; var content = this.QuotaExceededContent != null ? this.QuotaExceededContent(rateLimit, rateLimitPeriod) : string.Format(message, rateLimit, rateLimitPeriod); // break execution response.StatusCode = (int)QuotaExceededResponseCode; response.AddHeader("Retry-After", core.RetryAfterFrom(throttleCounter.Timestamp, rateLimitPeriod)); response.Write(content); return; } } } // no throttling required response.StatusCode = (int)HttpStatusCode.OK; return; }