How to throttle requests in a Web Api?

后端 未结 7 517
深忆病人
深忆病人 2020-11-30 17:45

I\'m trying to implement request throttling via the following:

Best way to implement request throttling in ASP.NET MVC?

I\'ve pulled that code into my solut

7条回答
  •  野性不改
    2020-11-30 18:27

    You seem to be confusing action filters for an ASP.NET MVC controller and action filters for an ASP.NET Web API controller. Those are 2 completely different classes:

    • For ASP.NET MVC: System.Web.Mvc.ActionFilterAttribute -> that's what you got from the link
    • For ASP.NET Web API: System.Web.Http.Filters.ActionFilterAttribute -> that's what you need to implement

    It appears that what you have shown is a Web API controller action (one that is declared inside a controller deriving from ApiController). So if you want to apply custom filters to it, they must derive from System.Web.Http.Filters.ActionFilterAttribute.

    So let's go ahead and adapt the code for Web API:

    public class ThrottleAttribute : ActionFilterAttribute
    {
        /// 
        /// A unique name for this Throttle.
        /// 
        /// 
        /// We'll be inserting a Cache record based on this name and client IP, e.g. "Name-192.168.0.1"
        /// 
        public string Name { get; set; }
    
        /// 
        /// The number of seconds clients must wait before executing this decorated route again.
        /// 
        public int Seconds { get; set; }
    
        /// 
        /// A text message that will be sent to the client upon throttling.  You can include the token {n} to
        /// show this.Seconds in the message, e.g. "Wait {n} seconds before trying again".
        /// 
        public string Message { get; set; }
    
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var key = string.Concat(Name, "-", GetClientIp(actionContext.Request));
            var allowExecute = false;
    
            if (HttpRuntime.Cache[key] == null)
            {
                HttpRuntime.Cache.Add(key,
                    true, // is this the smallest data we can have?
                    null, // no dependencies
                    DateTime.Now.AddSeconds(Seconds), // absolute expiration
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Low,
                    null); // no callback
    
                allowExecute = true;
            }
    
            if (!allowExecute)
            {
                if (string.IsNullOrEmpty(Message))
                {
                    Message = "You may only perform this action every {n} seconds.";
                }
    
                actionContext.Response = actionContext.Request.CreateResponse(
                    HttpStatusCode.Conflict, 
                    Message.Replace("{n}", Seconds.ToString())
                );
            }
        }
    }
    

    where the GetClientIp method comes from this post.

    Now you can use this attribute on your Web API controller action.

提交回复
热议问题