Limiter l'usage d'une API avec ASP.Net Web Api

icon Tags de l'article :

Juillet 04, 2016
Hello,

Petite classe perso qui permet de limiter très facilement une API (externe dans mon cas) à 20 appels par 20 secondes :

using System;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Caching;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

// source: http://stackoverflow.com/questions/20817300/how-to-throttle-requests-in-a-web-api

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ExternalApiThrottleAttribute : ActionFilterAttribute
{
    public const int DefaultDurationOfApiCallingPeriod = 20;
    public const int DefaultNumberOfCallsAllowedPerApiCallingPeriod = 20;

    public int CustomNumberOfCallsPerWindow { get; set; }

    public override void OnActionExecuting(HttpActionContext c)
    {
        if (CustomNumberOfCallsPerWindow == 0)
            CustomNumberOfCallsPerWindow = DefaultNumberOfCallsAllowedPerApiCallingPeriod;

        var allowExecute = false;

        var key = HttpContext.Current.User.Identity.Name;

        if (HttpRuntime.Cache[key] == null)
        {
            HttpRuntime.Cache.Add(key,
                1, // is this the smallest data we can have?
                null, // no dependencies
                DateTime.Now.AddSeconds(DefaultDurationOfApiCallingPeriod), // absolute expiration
                Cache.NoSlidingExpiration,
                CacheItemPriority.Low,
                null); // no callback

            allowExecute = true;
        }
        else
        {
            var previousNumberOfCalls = (int)HttpRuntime.Cache[key];
            if (previousNumberOfCalls < CustomNumberOfCallsPerWindow)
            {
                HttpRuntime.Cache[key] = previousNumberOfCalls + 1;

                allowExecute = true;
            }
        }

        if (!allowExecute)
        {
            c.Response = c.Request.CreateResponse(HttpStatusCode.Conflict, string.Format("You can't request that API so often. Your limit is {0} calls in {1} seconds.",
                CustomNumberOfCallsPerWindow,
                DefaultDurationOfApiCallingPeriod));
        }
    }
}

Et à l'usage, rien de plus simple :

[ExternalApiThrottle]
public IHttpActionResult GetCollection(ODataQueryOptions<Profiles> queryOptions)

Ou encore :

[ExternalApiThrottle(CustomNumberOfCallsPerWindow = 200)]
public IHttpActionResult GetCollection(ODataQueryOptions<Profiles> queryOptions)

A noter : ce code est loin d'être ce qu'il y a de mieux, et je recommande, si vous avez le temps, d'utiliser plutôt le package Nuget WebApiThrottle, bien plus complet et efficace. Je ne partage ce morceau de code que parce qu'il peut éventuellement aider des gens à créer par eux-même un ActionFilterAttribute pour limiter de façon perso l'usage de leur API.

Commentaires fermés

icon Flux RSS des commentaires de cet article

Les commentaires sont fermés pour cet article