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