When you’re building a web application, you need to think about how to handle requests. You might want to limit the number of requests per second your app can make, or you might want to throttle requests based on the time of day. In this article, we’ll show you how to do both of these things using Blazor and ASP.NET Core. We’ll also show you how to use the RequestLimitAttribute class to set a limit on individual requests. How Many Requests Can My App Make Per Second? The first thing you need to think about is how many requests your app can make per second. This is usually determined by the number of cores your computer has and the size of your application’s database. You can find out how many cores your computer has by opening System Information in Windows 10 or macOS and looking under “Processor Count” or “Processor Name” respectively. The number will be something like 4 or 8. If your application uses a database, then that will also affect the number of requests that can be made per second. If your database is large, then fewer requests per second will be allowed because it will take longer for the database to respond. If your database is small, then more requests per second will be allowed because it won’t take as long for the database to respond. How Do I Limit Requests Per Second? To limit the number of requests per second an app can make, use the RequestLimitAttribute class on an Action Method in your web application project: public ActionResult Index() { // … return View(); } [RequestLimit(50)] public ActionResult About() { // … return View(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 ..
If you’re making a public API or website, you’re probably worried about performance. Rate limiting can help prevent abuse from basic DDoS attacks, and it’s pretty easy to set up for Blazor/ASP.NET Core applications.
Why Rate Limit Requests?
There are plenty of reasons to rate limit requests. Most services should probably set some kind of rate limit, because no reasonable human is going to be making 100 requests a second for ten minutes straight. By default, your application is going to respond to every request, so setting a reasonable limit is a good idea.
Of course, your cloud provider may also have DDoS protection. This will usually protect well against Layer 3 and 4 attacks targeting your server. However, you’ll still want make sure your server does everything it can to block attackers from accessing it.
You also have the option of setting the limit much lower to limit requests on public APIs. For example, maybe a certain endpoint takes a lot of processing to respond to the request. You might want to limit this endpoint so that no single IP address can make more than a few requests every couple seconds, limiting stress on your server/database.
Setting Up Rate Limiting In ASP.NET Core
Blazor as a framework is built on top of ASP.NET Core, which handles all of the under-the-hood stuff for running an HTTP server and responding to requests. So, you’ll need to configure rate limiting for ASP.NET Core. The same steps will apply to anyone not using Blazor.
Rate limiting isn’t a default feature in ASP.NET Core unfortunately. However, there is a very popular NuGet package, AspNetCoreRateLimit, which does the job quite well. You can install it by right clicking your project in Visual Studio and selecting “Manage NuGet Packages…”:
Search for AspNetCoreRateLimit and install it.
There are a few ways to do rate limiting. If you’re using an API that needs keys, we recommend rate limiting based on API key, which covers all cases. For most people, rate limiting based on IP address is likely fine, and is the default recommended by AspNetCoreRateLimit.
You’ll need to add it as a service to ASP.NET. All services are configured in Startup.cs, which adds them with the ConfigureServices(IServiceCollection services) function.
There’s quite a few services to configure. The first function configures the services to load settings from your configuration file. You’ll also want to add Microsoft’s memory cache if you haven’t already. Then, you’ll need to configure IpRateLimiting from the JSON file, and then add the rate limiter.
Also in Startup.cs, you’ll need to configure the application builder to use IP rate limiting.
Keep in mind that this uses in-memory rate limiting, which is per-instance. If you’re load balancing your application, you’ll need to use a distributed memory store like Redis, which this package also has support for.
Configuring Rate Limiting
Once it’s added to ASP.NET, you’ll need to head over to your appsettings.json configuration file to set it up. The configuration looks something like the following:
First off, if you plan to rate limit certain endpoints differently, you’ll want to turn on EnableEndpointRateLimiting, which is false by default.
StackBlockedRequests will make any blocked requests count towards the counter. Basically, with this off, anyone making requests over and over will be served X responses per period. With it on, they’ll work up the max responses very quickly, and then won’t be responded too again.
RealIpHeader and ClientIdHeader used when your server is behind a reverse proxy, which is a common set up. Since the requests will always come from the proxy server, the proxy sets a header with the user’s actual info. You’ll need to check your proxy and ensure that this header is set correctly, or else the rate limiter will treat everyone as the same IP.
Then, there are three whitelists, one for IPs, client IDs, and endpoints. You can remove these if you don’t need them.
Then, you’ll need to configure each endpoint, as well as a period and limit. A wildcard will cover everything and is the only thing that works with EnableEndpointRateLimiting set to false. If it’s not, you can define endpoints using {HTTP_VERB}{PATH}, including wildcards, so *:/api/values will match all GET and POST requests to /api/values.
You’ll want to make sure that your endpoint matches a file, and not a directory. In my case, :/download//* was a valid endpoint, but :/download//*/ was not, because of the trailing slash.
This default config includes an IP whitelist for localhost, which you’ll need to comment out if you’re doing testing. But, you should be able to test your configuration by setting the limit very low, like 5 per minute, and making a bunch of requests. You should get this error, “API calls quota exceeded,” which means it’s working properly.
There’s a lot more that this package can do, so if you have more specific needs than this, we recommend checking out their documentation and seeing what’s possible.