예제 #1
0
        public async Task Invoke(HttpContext context)
        {
            var endpoint = context.GetEndpoint();

            RequestLimitAttribute requestLimit = endpoint?.Metadata.GetMetadata <RequestLimitAttribute>();
            RequestCount          requestCount = null;

            try
            {
                if (requestLimit != null)
                {
                    requestCount = _requestCounts.GetOrAdd(endpoint.DisplayName, (_) => new RequestCount());
                    int newRequestCount = requestCount.Increment();
                    if (newRequestCount > requestLimit.MaxConcurrency)
                    {
                        _logger.ThrottledEndpoint(requestLimit.MaxConcurrency, newRequestCount);
                        context.Response.StatusCode = (int)HttpStatusCode.TooManyRequests;
                        return;
                    }
                }

                await _next(context);
            }
            finally
            {
                //IMPORTANT This will not work for operation style apis, such as when returning a 202 for egress calls.
                requestCount?.Decrement();
            }
        }
예제 #2
0
        public async Task Invoke(HttpContext context)
        {
            var endpoint = context.GetEndpoint();

            RequestLimitAttribute requestLimit = endpoint?.Metadata.GetMetadata <RequestLimitAttribute>();
            IDisposable           incrementor  = null;

            try
            {
                //Operations and middleware both share the same increment limits, but
                //we don't want the middleware to increment the limit if the operation is doing it as well.
                if ((requestLimit != null) && !context.Request.Query.ContainsKey(EgressQuery))
                {
                    incrementor = _limitTracker.Increment(requestLimit.LimitKey, out bool allowOperation);
                    if (!allowOperation)
                    {
                        //We should report the same kind of error from Middleware and the Mvc layer.
                        context.Response.StatusCode  = StatusCodes.Status429TooManyRequests;
                        context.Response.ContentType = ContentTypes.ApplicationProblemJson;
                        await context.Response.WriteAsync(JsonSerializer.Serialize(new ProblemDetails
                        {
                            Status = StatusCodes.Status429TooManyRequests,
                            Detail = Microsoft.Diagnostics.Monitoring.WebApi.Strings.ErrorMessage_TooManyRequests
                        }), context.RequestAborted);

                        return;
                    }
                }

                await _next(context);
            }
            finally
            {
                incrementor?.Dispose();
            }
        }