public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken) { var context = actionContext; var request = new RateLimitingRequest( GetRouteTemplate(context), context.Request.RequestUri.AbsolutePath, context.Request.Method.Method, (header) => context.Request.Headers.GetValues(header).ToArray(), context.RequestContext.Principal as ClaimsPrincipal, await context.Request.Content.ReadAsStreamAsync().ConfigureAwait(false)); await _rateLimiter.LimitRequestAsync( request, () => RateLimitingFilter.GetCustomAttributes(context), context.Request.Headers.Host, onPostLimitFuncAsync : async(rateLimitingRequest, policy, rateLimitingResult) => { context.Request.Properties.Add($"RateLimitingResult_{_filterId}", rateLimitingResult); var clientDecision = OnPostLimit != null ? await OnPostLimit.Invoke(rateLimitingRequest, policy, rateLimitingResult, actionContext).ConfigureAwait(false) : Decision.OK; var reverted = await RevertIfRequired(rateLimitingResult, context, request, policy, clientDecision).ConfigureAwait(false); if (reverted) { await base.OnAuthorizationAsync(context, cancellationToken).ConfigureAwait(false); return; } if (rateLimitingResult.State == ResultState.Success) { if (PostOperationDecisionFuncAsync != null) { context.Request.Properties.Add($"PostActionFilterFuncAsync_{_filterId}", new Func <HttpActionExecutedContext, Task>(async(httpActionExecutedContext) => { var decision = await PostOperationDecisionFuncAsync.Invoke(rateLimitingRequest, policy, rateLimitingResult, httpActionExecutedContext).ConfigureAwait(false); await RevertIfRequired(rateLimitingResult, context, request, policy, decision).ConfigureAwait(false); })); } await base.OnAuthorizationAsync(context, cancellationToken).ConfigureAwait(false); } else if ((rateLimitingResult.State == ResultState.Throttled || rateLimitingResult.State == ResultState.ThrottledButCompensationFailed) && !SimulationMode) { await TooManyRequests(context, rateLimitingResult, policy.Name).ConfigureAwait(false); } }, getPolicyFuncAsync : GetPolicyFuncAsync != null?new Func <RateLimitingRequest, Task <RateLimitPolicy> >(async(rlr) => { return(await GetPolicyFuncAsync.Invoke(rlr, actionContext).ConfigureAwait(false)); }) : null ).ConfigureAwait(false); }
private async Task <bool> RevertIfRequired(RateLimitingResult rateLimitingResult, HttpActionContext context, RateLimitingRequest request, RateLimitPolicy policy, Decision decision) { if (decision == Decision.REVERTSUCCESSCOST && rateLimitingResult.State == ResultState.Success) { await _rateLimiter.LimitRequestAsync(request, () => RateLimitingFilter.GetCustomAttributes(context), context.Request.Headers.Host, getPolicyFuncAsync : _ => Task.FromResult(policy), onPostLimitFuncAsync : async(rateLimitingRequest, postPolicy, rateLimitingRevertResult) => { if (rateLimitingRevertResult.State == ResultState.Success) { context.Request.Properties[$"RateLimitingResult_{_filterId}"] = rateLimitingRevertResult; } if (OnPostLimitRevert != null) { await OnPostLimitRevert.Invoke(request, postPolicy, rateLimitingRevertResult, context).ConfigureAwait(false); } }, revert : true).ConfigureAwait(false); return(await Task.FromResult(true)); } return(await Task.FromResult(false)); }