Limit the simultaneous requests served by the ASP.NET Web API

OWIN middleware to apply limits to an OWIN pipeline:

  • Max bandwidth
  • Max concurrent requests
  • Connection timeout
  • Max query string
  • Max request content length
  • Max url length
  • Min response delay

You could add a piece of OwinMiddleware along these lines (influenced by the WebApiThrottle you linked to):

public class MaxConccurrentMiddleware : OwinMiddleware
{
    private readonly int maxConcurrentRequests;
    private int currentRequestCount;

    public MaxConccurrentMiddleware(int maxConcurrentRequests)
    {
        this.maxConcurrentRequests = maxConcurrentRequests;
    }

    public override async Task Invoke(IOwinContext context)
    {
        try
        {
            if (Interlocked.Increment(ref currentRequestCount) > maxConcurrentRequests)
            {
                var response = context.Response;

                response.OnSendingHeaders(state =>
                {
                    var resp = (OwinResponse)state;
                    resp.StatusCode = 429; // 429 Too Many Requests
                }, response);

                return Task.FromResult(0);
            }

            await Next.Invoke(context);
        }
        finally
        {
            Interlocked.Decrement(ref currentRequestCount);
        }
    }
}

Alternatively you can use a git package to deal with this:

 

Installation

There are two nuget packages. The main one is pure owin and this has no dependencies.

install-package LimitsMiddleware

The second package provides integration with IAppBuilder, which is deprecated but provided here for legacy and compatability reasons.

install-package LimitsMiddleware.OwinAppBuilder

An asp.net vNext builder integration package will be forthcoming.

Using

Configuration values can be supplied as constants or with a delegate. The latter allows you to change the values at runtime. Use which ever you see fit. This code assumes you have installed ‘LimitsMiddleware.OwinAppBuilder’

public class Startup
{
    public void Configuration(IAppBuilder builder)
    {
        //static settings
        builder.Use()
            .MaxBandwidth(10000) //bps
            .MaxConcurrentRequests(10)
            .ConnectionTimeout(TimeSpan.FromSeconds(10))
            .MaxQueryStringLength(15) //Unescaped QueryString
            .MaxRequestContentLength(15)
            .MaxUrlLength(20)
            .MinResponseDelay(200ms)
            .UseEtc(..);

        //dynamic settings
        builder.Use()
            .MaxBandwidth(() => 10000) //bps
            .MaxConcurrentRequests(() => 10)
            .ConnectionTimeout(() => TimeSpan.FromSeconds(10))
            .MaxQueryStringLength(() => 15)
            .MaxRequestContentLength(() => 15)
            .MaxUrlLength(() => 20)
            .UseEtc(..);
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s