private bool ApplyThrottling(HttpActionContext filterContext, out EnableThrottlingAttribute attr) { var applyThrottling = false; attr = null; if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes <EnableThrottlingAttribute>(true).Count > 0) { attr = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes <EnableThrottlingAttribute>(true).First(); applyThrottling = true; } if (filterContext.ActionDescriptor.GetCustomAttributes <EnableThrottlingAttribute>(true).Count > 0) { attr = filterContext.ActionDescriptor.GetCustomAttributes <EnableThrottlingAttribute>(true).First(); applyThrottling = true; } // explicit disabled if (filterContext.ActionDescriptor.GetCustomAttributes <DisableThrottingAttribute>(true).Count > 0) { applyThrottling = false; } return(applyThrottling); }
public override void OnActionExecuting(HttpActionContext actionContext) { EnableThrottlingAttribute attrPolicy = null; var applyThrottling = ApplyThrottling(actionContext, out attrPolicy); // get policy from repo if (policyRepository != null) { policy = policyRepository.FirstOrDefault(ThrottleManager.GetPolicyKey()); } if (Policy != null && applyThrottling) { core.Repository = Repository; core.Policy = Policy; var identity = SetIndentity(actionContext.Request); if (!core.IsWhitelisted(identity)) { 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 EnableThrottlingAttribute policy var attrLimit = attrPolicy.GetLimit(rateLimitPeriod); if (attrLimit > 0) { rateLimit = attrLimit; } // apply global rules core.ApplyRules(identity, timeSpan, rateLimitPeriod, ref rateLimit); if (rateLimit > 0) { // increment counter string requestId; var throttleCounter = core.ProcessRequest(identity, timeSpan, rateLimitPeriod, out 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, actionContext.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); // add status code and retry after x seconds to response actionContext.Response = QuotaExceededResponse( actionContext.Request, string.Format(message, rateLimit, rateLimitPeriod), QuotaExceededResponseCode, core.RetryAfterFrom(throttleCounter.Timestamp, rateLimitPeriod)); } } } } } base.OnActionExecuting(actionContext); }
private bool ApplyThrottling(HttpActionContext filterContext, out EnableThrottlingAttribute attr) { var applyThrottling = false; attr = null; if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<EnableThrottlingAttribute>(true).Any()) { attr = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<EnableThrottlingAttribute>(true).First(); applyThrottling = true; } if (filterContext.ActionDescriptor.GetCustomAttributes<EnableThrottlingAttribute>(true).Any()) { attr = filterContext.ActionDescriptor.GetCustomAttributes<EnableThrottlingAttribute>(true).First(); applyThrottling = true; } // explicit disabled if (filterContext.ActionDescriptor.GetCustomAttributes<DisableThrottingAttribute>(true).Any()) { applyThrottling = false; } return applyThrottling; }