Skip to content

Instantly share code, notes, and snippets.

@0x49D1
Created December 18, 2023 07:59
Show Gist options
  • Save 0x49D1/69a9d097c34b0f5384fc64d76c68be71 to your computer and use it in GitHub Desktop.
Save 0x49D1/69a9d097c34b0f5384fc64d76c68be71 to your computer and use it in GitHub Desktop.
Simple attribute used to rate limit requests based on IP address and path.
/* Sample usage in controller action
[HttpPost]
[Route("in/batch-update")]
[RateLimit]
public virtual async Task<IActionResult> BatchUpdate(SomeModel model)
{...}
*/
/// <summary>
/// Attribute used to rate limit requests based on IP address and path.
/// </summary>
public class RateLimitAttribute : TypeFilterAttribute
{
public RateLimitAttribute(int limit = 100, int seconds = 30) : base(typeof(RateLimitFilter))
{
Arguments = new object[] { limit, seconds };
}
private class RateLimitFilter : IActionFilter
{
private static Dictionary<string, Tuple<DateTime, int>> _requests = new Dictionary<string, Tuple<DateTime, int>>();
private readonly int _limit;
private readonly int _seconds;
private readonly ILogger _logger;
public RateLimitFilter(ILogger<RateLimitFilter> logger, int limit, int seconds)
{
_logger = logger;
_limit = limit;
_seconds = seconds;
}
public void OnActionExecuting(ActionExecutingContext context)
{
var ip = context.HttpContext.Connection.RemoteIpAddress.ToString();
var path = context.HttpContext.Request.Path;
var key = $"{ip}-{path}";
if (_requests.ContainsKey(key))
{
var value = _requests[key];
if (value.Item1.AddSeconds(_seconds) > DateTime.Now)
{
if (value.Item2 > _limit)
{
_logger.LogWarning("Rate limit exceeded for {Key}", key);
context.Result = new StatusCodeResult(429); // Too many requests
return;
}
else
{
_requests[key] = Tuple.Create(value.Item1, value.Item2 + 1);
}
}
else
{
_requests.Remove(key);
}
}
if (!_requests.ContainsKey(key))
{
_requests.Add(key, Tuple.Create(DateTime.Now, 1));
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment