Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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));
        }