Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jessebarocio
Last active June 13, 2021 18:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jessebarocio/5a33486c556e4cfb8b3d0942d4ae5917 to your computer and use it in GitHub Desktop.
Save jessebarocio/5a33486c556e4cfb8b3d0942d4ae5917 to your computer and use it in GitHub Desktop.
Implementing and registering a message handler in ASP.NET Web API 2
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace MyApi.Infrastructure
{
public class RateLimitingHandler : DelegatingHandler
{
private const string RateLimitHeaderName = "X-MyApi-Rate-Limit-Remaining";
// The service that handles tracking rate limits for API consumers.
RateLimitingService _service = new RateLimitingService();
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response;
// Get the token that is making this request.
string consumerToken = request.Headers.Authorization.Parameter;
// Get the number of calls that this token is authorized to make.
int remainingCalls = _service.GetRemainingCalls(consumerToken);
// If the number of calls < 1 then the consumer has hit their rate limit.
// Return an appropriate response.
if(remainingCalls < 1)
{
response = request.CreateResponse(
(HttpStatusCode)429, new { Message = "Rate limit exceeded!" });
}
else // Otherwise return the response from the controller.
{
response = await base.SendAsync(request, cancellationToken);
// Append a custom header so the API consumer can see the remaining request limit.
response.Headers.Add(RateLimitHeaderName, (--remainingCalls).ToString());
}
return response;
}
}
}
using MyApi.Infrastructure;
using System.Web.Http;
namespace MyApi
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// Register as a global handler - all Web API requests will go through
// RateLimitingHandler.
config.MessageHandlers.Add(new RateLimitingHandler());
// -- OR --
// Register the handler for a specific route - only Web API requests
// that match this route will go through RateLimitingHandler.
config.Routes.MapHttpRoute(
name: "TasksApi",
routeTemplate: "api/Tasks/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: new RateLimitingHandler()
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment