### Define Rate Limits via web.config or app.config Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md This example illustrates how to define throttling policies using XML configuration in `web.config` or `app.config`. It includes settings for global limits, IP rules, client key rules, endpoint rules, and whitelists, providing a declarative way to manage throttling. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = ThrottlePolicy.FromStore(new PolicyConfigurationProvider()), Repository = new CacheRepository() }); ``` ```xml
``` -------------------------------- ### Configure Global IP Throttling Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Sets up global request rate limits based on IP addresses. Includes examples for standard ASP.NET Web API and OWIN self-hosted environments. ```csharp public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000) { IpThrottling = true }, Repository = new CacheRepository() }); } } ``` ```csharp public class Startup { public void Configuration(IAppBuilder appBuilder) { HttpConfiguration config = new HttpConfiguration(); config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000) { IpThrottling = true }, Repository = new MemoryCacheRepository() }); appBuilder.UseWebApi(config); } } ``` -------------------------------- ### Implement RedisThrottleRepository for Distributed Storage Source: https://context7.com/stefanprodan/webapithrottle/llms.txt This C# code provides an implementation of the IThrottleRepository interface using Redis for storing throttle counters. It supports operations like checking existence, retrieving counters, saving, removing, and clearing. This is crucial for scaling throttling logic across multiple servers. The example demonstrates connecting to Redis and configuring the ThrottlingHandler. ```csharp public interface IThrottleRepository { bool Any(string id); ThrottleCounter? FirstOrDefault(string id); void Save(string id, ThrottleCounter throttleCounter, TimeSpan expirationTime); void Remove(string id); void Clear(); } // Redis implementation example public class RedisThrottleRepository : IThrottleRepository { private readonly IDatabase _redis; public RedisThrottleRepository(IConnectionMultiplexer connection) { _redis = connection.GetDatabase(); } public bool Any(string id) { return _redis.KeyExists(id); } public ThrottleCounter? FirstOrDefault(string id) { var value = _redis.StringGet(id); if (value.IsNullOrEmpty) return null; return JsonConvert.DeserializeObject(value); } public void Save(string id, ThrottleCounter throttleCounter, TimeSpan expirationTime) { var value = JsonConvert.SerializeObject(throttleCounter); _redis.StringSet(id, value, expirationTime); } public void Remove(string id) { _redis.KeyDelete(id); } public void Clear() { // Implement pattern-based deletion or use separate database } } // Usage with Redis repository public static class WebApiConfig { public static void Register(HttpConfiguration config) { var redis = ConnectionMultiplexer.Connect("localhost:6379"); config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 10, perMinute: 100) { IpThrottling = true }, Repository = new RedisThrottleRepository(redis) }); } } ``` -------------------------------- ### Implement DatabaseThrottleLogger for Request Logging Source: https://context7.com/stefanprodan/webapithrottle/llms.txt This C# code implements the IThrottleLogger interface to log throttled requests into a database via an ILogRepository. It captures details like timestamp, request ID, client IP, endpoint, and rate limit information. The example also shows how to integrate TracingThrottleLogger with System.Diagnostics.TraceWriter for debugging. ```csharp public class DatabaseThrottleLogger : IThrottleLogger { private readonly ILogRepository _repository; public DatabaseThrottleLogger(ILogRepository repository) { _repository = repository; } public void Log(ThrottleLogEntry entry) { _repository.Insert(new ThrottleLog { Timestamp = entry.LogDate, RequestId = entry.RequestId, ClientIp = entry.ClientIp, ClientKey = entry.ClientKey, Endpoint = entry.Endpoint, RateLimit = entry.RateLimit, RateLimitPeriod = entry.RateLimitPeriod, TotalRequests = entry.TotalRequests }); } } // Built-in TracingThrottleLogger usage public static class WebApiConfig { public static void Register(HttpConfiguration config) { var traceWriter = new SystemDiagnosticsTraceWriter() { IsVerbose = true }; config.Services.Replace(typeof(ITraceWriter), traceWriter); config.EnableSystemDiagnosticsTracing(); config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true }, Repository = new CacheRepository(), Logger = new TracingThrottleLogger(traceWriter) }); } } // Output when request is blocked: // 2024-01-15T10:30:45Z Request throttle_192.168.1.100_/api/values_Second // from 192.168.1.100 has been throttled (blocked), quota 1/Second exceeded by 3 ``` -------------------------------- ### ThrottlingFilter: Attribute-Based Rate Limiting (C#) Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Implements rate limiting using ThrottlingFilter, an ActionFilterAttribute, enabling per-controller and per-action rate limits via EnableThrottlingAttribute and DisableThrottingAttribute decorators. This example shows global filter registration and applying custom limits at controller and action levels. ```csharp // Register the filter globally public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Filters.Add(new ThrottlingFilter() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200) { IpThrottling = true, IpWhitelist = new List { "127.0.0.1" }, ClientThrottling = true, ClientWhitelist = new List { "admin-key" }, EndpointThrottling = true }, Repository = new CacheRepository() }); } } // Apply custom rate limits at controller level [EnableThrottling(PerSecond = 2, PerMinute = 30)] public class ProductsController : ApiController { // Inherits controller-level limits: 2/sec, 30/min public IEnumerable Get() { return _repository.GetAll(); } // Override with action-level limits [EnableThrottling(PerSecond = 1, PerMinute = 10, PerHour = 100)] public Product Get(int id) { return _repository.GetById(id); } // Disable throttling for this action [DisableThrotting] public HttpResponseMessage Head() { return Request.CreateResponse(HttpStatusCode.OK); } // Heavy operation with stricter limits [EnableThrottling(PerMinute = 5, PerHour = 20)] public IEnumerable Search(string query) { return _repository.Search(query); } } ``` -------------------------------- ### Implement Custom Storage Repositories Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Define custom storage backends for throttle metrics and policies by implementing the IThrottleRepository and IPolicyRepository interfaces. ```csharp public interface IThrottleRepository { bool Any(string id); ThrottleCounter? FirstOrDefault(string id); void Save(string id, ThrottleCounter throttleCounter, TimeSpan expirationTime); void Remove(string id); Clear(); } public interface IPolicyRepository { ThrottlePolicy FirstOrDefault(string id); void Remove(string id); void Save(string id, ThrottlePolicy policy); } ``` -------------------------------- ### Configure Cache Key Prefixes and Suffixes in C# Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Demonstrates how to configure global prefixes and suffixes for cache keys used by ThrottleManager. This is useful for multi-tenant applications or distinguishing between different API versions by customizing the base names for throttle and policy keys. ```csharp // Configure global prefix for cache keys public class Global : HttpApplication { protected void Application_Start() { // Set application-specific prefix for cache keys ThrottleManager.ApplicationName = "MyApi_v2_"; // Customize throttle key prefix (default: "throttle") ThrottleManager.ThrottleKey = "rate_limit"; // Customize policy key suffix (default: "throttle_policy") ThrottleManager.PolicyKey = "policy"; // Resulting cache keys: // Rate limits: "MyApi_v2_rate_limit_{identity}_{period}" // Policy: "MyApi_v2_policy" GlobalConfiguration.Configure(WebApiConfig.Register); } } // Get cache keys for manual operations public class DiagnosticsController : ApiController { public IHttpActionResult GetCacheInfo() { return Ok(new { ThrottleKeyPrefix = ThrottleManager.GetThrottleKey(), // "MyApi_v2_rate_limit" PolicyKey = ThrottleManager.GetPolicyKey() // "MyApi_v2_policy" }); } } ``` -------------------------------- ### Implement and Configure Custom Logging Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Create a custom logger by implementing IThrottleLogger and attach it to the ThrottlingHandler to track blocked requests. ```csharp public interface IThrottleLogger { void Log(ThrottleLogEntry entry); } public class TracingThrottleLogger : IThrottleLogger { private readonly ITraceWriter traceWriter; public TracingThrottleLogger(ITraceWriter traceWriter) { this.traceWriter = traceWriter; } public void Log(ThrottleLogEntry entry) { if (null != traceWriter) { traceWriter.Info(entry.Request, "WebApiThrottle", "{0} Request {1} from {2} has been throttled (blocked), quota {3}/{4} exceeded by {5}", entry.LogDate, entry.RequestId, entry.ClientIp, entry.RateLimit, entry.RateLimitPeriod, entry.TotalRequests); } } } ``` -------------------------------- ### Apply EnableThrottling Attributes to Controllers Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Demonstrates how to use EnableThrottling and DisableThrottling attributes to override global rate limits at the controller and action levels. ```csharp [EnableThrottling(PerSecond = 2)] public class ValuesController : ApiController { [EnableThrottling(PerSecond = 1, PerMinute = 30, PerHour = 100)] public IEnumerable Get() { return new string[] { "value1", "value2" }; } [DisableThrotting] public string Get(int id) { return "value"; } } ``` -------------------------------- ### Implement ThrottlingHandler in Web API Pipeline Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Demonstrates how to register the ThrottlingHandler in both standard IIS-hosted Web API and self-hosted OWIN environments. It shows the initialization of the message handler with a specific policy and repository. ```csharp public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200) { IpThrottling = true }, Repository = new CacheRepository() }); } } public class Startup { public void Configuration(IAppBuilder appBuilder) { HttpConfiguration config = new HttpConfiguration(); config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 2, perMinute: 60, perHour: 500) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true }, Repository = new MemoryCacheRepository() }); config.MapHttpAttributeRoutes(); appBuilder.UseWebApi(config); } } ``` -------------------------------- ### Configure ThrottlingMiddleware for OWIN Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Configures ThrottlingMiddleware within the OWIN Startup class for both self-hosted and IIS-hosted environments. ```csharp public class Startup { public void Configuration(IAppBuilder appBuilder) { appBuilder.Use(typeof(ThrottlingMiddleware), ThrottlePolicy.FromStore(new PolicyConfigurationProvider()), new PolicyMemoryCacheRepository(), new MemoryCacheRepository(), null, null); } } ``` -------------------------------- ### Configure IP and Client Whitelisting Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Bypasses throttling for specific IP addresses or client keys. Supports CIDR notation and IP ranges. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 2, perMinute: 60) { IpThrottling = true, IpWhitelist = new List { "::1", "192.168.0.0/24" }, ClientThrottling = true, ClientWhitelist = new List { "admin-key" } }, Repository = new CacheRepository() }); ``` -------------------------------- ### Configure IP and Client Key Custom Rate Limits in C# Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md This snippet demonstrates how to define custom rate limits for specific IP addresses, IP ranges, and client keys that override the default throttling policy. It requires a global counterpart policy to be defined for custom rules to take effect. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500) { IpThrottling = true, IpRules = new Dictionary { { "192.168.1.1", new RateLimits { PerSecond = 2 } }, { "192.168.2.0/24", new RateLimits { PerMinute = 30, PerHour = 30*60, PerDay = 30*60*24 } } }, ClientThrottling = true, ClientRules = new Dictionary { { "api-client-key-1", new RateLimits { PerMinute = 40, PerHour = 400 } }, { "api-client-key-9", new RateLimits { PerDay = 2000 } } } }, Repository = new CacheRepository() }); ``` -------------------------------- ### Implement CustomIpAddressParser for Load Balancers Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Implements the IIpAddressParser interface to correctly resolve client IP addresses when the application is behind proxies like Cloudflare or AWS ALB. It checks specific headers before falling back to default parsing logic. ```csharp public class CustomIpAddressParser : DefaultIpAddressParser { public override IPAddress GetClientIp(HttpRequestMessage request) { if (request.Headers.Contains("CF-Connecting-IP")) { var headerValue = request.Headers.GetValues("CF-Connecting-IP").FirstOrDefault(); if (!string.IsNullOrEmpty(headerValue)) { return ParseIp(headerValue.Trim()); } } if (request.Headers.Contains("X-Forwarded-For")) { var headerValue = request.Headers.GetValues("X-Forwarded-For").FirstOrDefault(); if (!string.IsNullOrEmpty(headerValue)) { var firstIp = headerValue.Split(',').FirstOrDefault(); if (!string.IsNullOrEmpty(firstIp)) { return ParseIp(firstIp.Trim()); } } } return base.GetClientIp(request); } } public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler( policy: new ThrottlePolicy(perSecond: 5, perMinute: 100) { IpThrottling = true }, policyRepository: new PolicyCacheRepository(), repository: new CacheRepository(), logger: null, ipAddressParser: new CustomIpAddressParser())); } } ``` -------------------------------- ### Custom Storage Repositories Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Interfaces for implementing custom storage backends for throttle metrics and policies. ```APIDOC ## Interface Definitions ### Description Implement these interfaces to store throttle counters or policies in external systems like Redis, SQL, or NoSQL databases. ### IThrottleRepository - **Any(string id)**: Checks if a record exists. - **FirstOrDefault(string id)**: Retrieves a counter. - **Save(string id, ThrottleCounter counter, TimeSpan expiration)**: Persists a counter. - **Remove(string id)**: Deletes a counter. ### IPolicyRepository - **FirstOrDefault(string id)**: Retrieves a policy. - **Save(string id, ThrottlePolicy policy)**: Persists a policy. ``` -------------------------------- ### Define ThrottlePolicy via XML Configuration Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Shows how to define rate limiting rules, whitelists, and policy settings within a web.config or app.config file. This allows for dynamic policy updates without recompiling the application. ```xml
``` -------------------------------- ### Register ThrottlingHandler with XML Policy Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Demonstrates how to load the XML-defined policy into the Web API pipeline using the ThrottlingHandler within the WebApiConfig registration. ```csharp public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler() { Policy = ThrottlePolicy.FromStore(new PolicyConfigurationProvider()), Repository = new CacheRepository() }); } } ``` -------------------------------- ### Global Throttling with Owin Self-Hosting Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Configures global throttling for Owin self-hosted Web APIs using MemoryCacheRepository. ```APIDOC ## Global Throttling with Owin Self-Hosting ### Description This configuration is for WebApi applications self-hosted with Owin. It uses `MemoryCacheRepository` for storing throttling data in the application's runtime memory. ### Method Not Applicable (Configuration via Message Handler) ### Endpoint Not Applicable (Applies globally) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cs public class Startup { public void Configuration(IAppBuilder appBuilder) { HttpConfiguration config = new HttpConfiguration(); config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000) { IpThrottling = true }, Repository = new MemoryCacheRepository() }); appBuilder.UseWebApi(config); } } ``` ### Response #### Success Response (200) Requests within the defined limits are processed normally. #### Response Example None (This is a configuration example) ### Error Handling Requests exceeding the limits will receive a `429 Too Many Requests` status code. ``` -------------------------------- ### Configure Client Key and Endpoint Throttling Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Combines IP, Client Key, and Endpoint throttling to provide granular control over API usage based on identity. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository() }); ``` -------------------------------- ### IP and/or Client Key White-listing Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Configures white-lists for IP addresses and client keys, bypassing throttling for specified entries. ```APIDOC ## IP and/or Client Key White-listing ### Description This feature allows you to exempt specific IP addresses or client API keys from throttling. Requests originating from white-listed IPs or using white-listed client keys will not be subject to rate limits and will not be stored by the throttling repository. Supports IP ranges for IPv4 and IPv6. ### Method Not Applicable (Configuration via Message Handler) ### Endpoint Not Applicable (Applies globally or to configured endpoints) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cs config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 2, perMinute: 60) { IpThrottling = true, IpWhitelist = new List { "::1", "192.168.0.0/24" }, ClientThrottling = true, ClientWhitelist = new List { "admin-key" } }, Repository = new CacheRepository() }); ``` ### Response #### Success Response (200) Requests from white-listed IPs or clients are processed without throttling. #### Response Example None (This is a configuration example) ### Error Handling Throttling is bypassed for white-listed entries. Non-white-listed requests are subject to normal throttling rules. ``` -------------------------------- ### OWIN ThrottlingMiddleware Configuration Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Configures the ThrottlingMiddleware within an OWIN startup class to intercept and throttle requests before they reach the Web API pipeline. ```APIDOC ## OWIN Middleware Configuration ### Description Integrates the ThrottlingMiddleware into the OWIN pipeline to enforce rate limits on all incoming requests, including OAuth and SignalR endpoints. ### Method N/A (Middleware Registration) ### Endpoint Global Application Pipeline ### Parameters #### Request Body - **appBuilder** (IAppBuilder) - Required - The OWIN application builder instance. - **policy** (ThrottlePolicy) - Required - The policy defining rate limits (IP, Client, or Endpoint). - **repository** (ICacheRepository) - Required - The storage mechanism for tracking request counts. ### Request Example appBuilder.Use(typeof(ThrottlingMiddleware), new ThrottlePolicy(perSecond: 5, perMinute: 100) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true }); ### Response #### Success Response (200) - **Status** (HTTP 200) - Request allowed. #### Error Response (429) - **Status** (HTTP 429) - Too Many Requests (Rate limit exceeded). ``` -------------------------------- ### Implement Custom IP Address Parsing Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Shows how to inject a custom IP address parser into the ThrottlingHandler to extract client IPs from specific headers. ```csharp config.MessageHandlers.Add(new ThrottlingHandler( policy: new ThrottlePolicy(perMinute: 20, perHour: 30, perDay: 35, perWeek: 3000) { IpThrottling = true }, policyRepository: new PolicyCacheRepository(), repository: new CacheRepository(), logger: new TracingThrottleLogger(traceWriter), ipAddressParser: new CustomIpAddressParser())); ``` -------------------------------- ### Runtime Policy Updates Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Explains how to update rate limiting policies dynamically at runtime using the ThrottleManager and a policy repository. ```APIDOC ## POST /internal/throttle/update-policy ### Description Updates the active rate limiting policy for clients or endpoints at runtime without restarting the application. ### Method POST ### Endpoint Internal method: ThrottleManager.UpdatePolicy(ThrottlePolicy policy, IPolicyRepository repository) ### Parameters #### Request Body - **policy** (ThrottlePolicy) - Required - The updated policy object containing new rate limits. - **repository** (IPolicyRepository) - Required - The repository instance used to persist the policy. ### Request Example { "policy": { "ClientRules": { "api-client-key-1": { "PerMinute": 80, "PerHour": 800 } } } } ### Response #### Success Response (200) - **status** (string) - Indicates successful update of the policy in the repository. ``` -------------------------------- ### ThrottlingHandler: Runtime Policy Updates with PolicyCacheRepository (C#) Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Configures the ThrottlingHandler to support runtime policy updates by integrating with PolicyCacheRepository. This allows dynamic modification of rate limits without restarting the application. It registers the handler with a specified throttle policy, policy repository, cache repository, and logger. ```csharp public static class WebApiConfig { public static void Register(HttpConfiguration config) { var traceWriter = new SystemDiagnosticsTraceWriter() { IsVerbose = true }; config.Services.Replace(typeof(ITraceWriter), traceWriter); config.EnableSystemDiagnosticsTracing(); // Register handler with policy repository for runtime updates config.MessageHandlers.Add(new ThrottlingHandler( policy: new ThrottlePolicy(perMinute: 20, perHour: 200, perDay: 2000) { IpThrottling = true, ClientThrottling = true, ClientRules = new Dictionary { { "client-key-1", new RateLimits { PerMinute = 60, PerHour = 600 } } }, EndpointThrottling = true }, policyRepository: new PolicyCacheRepository(), repository: new CacheRepository(), logger: new TracingThrottleLogger(traceWriter))); } } // Update policy at runtime from anywhere in your application public class RateLimitService { public void UpdateClientLimits(string clientKey, int perMinute, int perHour) { var policyRepository = new PolicyCacheRepository(); var policy = policyRepository.FirstOrDefault(ThrottleManager.GetPolicyKey()); if (policy.ClientRules.ContainsKey(clientKey)) { policy.ClientRules[clientKey] = new RateLimits { PerMinute = perMinute, PerHour = perHour }; } else { policy.ClientRules.Add(clientKey, new RateLimits { PerMinute = perMinute, PerHour = perHour }); } ThrottleManager.UpdatePolicy(policy, policyRepository); } } ``` -------------------------------- ### Update Rate Limits at Runtime Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Modify throttling policies dynamically at runtime by retrieving the current policy from the repository, updating rules, and applying changes via ThrottleManager. ```csharp public void UpdateRateLimits() { var policyRepository = new PolicyCacheRepository(); var policy = policyRepository.FirstOrDefault(ThrottleManager.GetPolicyKey()); policy.ClientRules["api-client-key-1"] = new RateLimits { PerMinute = 80, PerHour = 800 }; policy.ClientRules.Add("api-client-key-3", new RateLimits { PerMinute = 60, PerHour = 600 }); ThrottleManager.UpdatePolicy(policy, policyRepository); } ``` -------------------------------- ### Retrieve API Client Key with Custom Logic in C# Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md This C# code defines a custom ThrottlingHandler to override the default method of retrieving API client keys. It demonstrates how to extract the client key from a different request header ('Authorization-Key') or default to 'anon' if the header is not present, while still capturing client IP and endpoint. ```csharp public class CustomThrottlingHandler : ThrottlingHandler { protected override RequestIdentity SetIdentity(HttpRequestMessage request) { return new RequestIdentity() { ClientKey = request.Headers.Contains("Authorization-Key") ? request.Headers.GetValues("Authorization-Key").First() : "anon", ClientIp = base.GetClientIp(request).ToString(), Endpoint = request.RequestUri.AbsolutePath.ToLowerInvariant() }; } } ``` -------------------------------- ### Configure Stack Blocked Requests in C# Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md This snippet shows how to configure the ThrottlingHandler to stack blocked requests. By setting `StackBlockedRequests` to true, rejected requests will be counted towards the minute, hour, and day limits, unlike the default behavior where only successful requests are counted. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true, StackBlockedRequests = true }, Repository = new CacheRepository() }); ``` -------------------------------- ### Global Throttling based on IP Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Configures global throttling for all requests originating from the same IP address. Limits are set per second, minute, hour, day, and week. ```APIDOC ## Global Throttling based on IP ### Description This setup limits the number of requests originated from the same IP address. If multiple calls are made to different endpoints within the same second from the same IP, subsequent calls after the first will be blocked according to the defined policy. ### Method Not Applicable (Configuration via Message Handler) ### Endpoint Not Applicable (Applies globally) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cs public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000) { IpThrottling = true }, Repository = new CacheRepository() }); } } ``` ### Response #### Success Response (200) Requests within the defined limits are processed normally. #### Response Example None (This is a configuration example) ### Error Handling Requests exceeding the limits will receive a `429 Too Many Requests` status code. ``` -------------------------------- ### Implement CustomThrottlingHandler for Client Identity Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Extends the ThrottlingHandler class to define custom logic for identifying clients via headers or OAuth tokens. This allows for granular rate limiting based on specific application-level identifiers. ```csharp public class CustomThrottlingHandler : ThrottlingHandler { protected override RequestIdentity SetIdentity(HttpRequestMessage request) { string clientKey = "anon"; if (request.Headers.Contains("X-API-Key")) { clientKey = request.Headers.GetValues("X-API-Key").First(); } else if (request.Headers.Authorization != null) { clientKey = request.Headers.Authorization.Parameter ?? "anon"; } return new RequestIdentity() { ClientKey = clientKey, ClientIp = base.GetClientIp(request).ToString(), Endpoint = request.RequestUri.AbsolutePath.ToLowerInvariant() }; } } public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new CustomThrottlingHandler() { Policy = new ThrottlePolicy(perMinute: 30, perHour: 500) { IpThrottling = true, ClientThrottling = true, ClientRules = new Dictionary { { "premium-token", new RateLimits { PerMinute = 100 } }, { "basic-token", new RateLimits { PerMinute = 20 } } } }, Repository = new CacheRepository() }); } } ``` -------------------------------- ### Configure ThrottlePolicy for Rate Limiting Rules Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Defines global and specific rate limiting rules, including IP whitelisting and custom limits for clients or endpoints. This configuration class is central to managing how requests are throttled across the application. ```csharp var policy = new ThrottlePolicy( perSecond: 1, perMinute: 20, perHour: 200, perDay: 1500, perWeek: 3000 ) { IpThrottling = true, IpWhitelist = new List { "127.0.0.1", "192.168.0.0/24" }, IpRules = new Dictionary { { "192.168.1.1", new RateLimits { PerSecond = 5, PerMinute = 50 } }, { "10.0.0.0/8", new RateLimits { PerHour = 1000, PerDay = 10000 } } }, ClientThrottling = true, ClientWhitelist = new List { "admin-key", "premium-key" }, ClientRules = new Dictionary { { "api-client-basic", new RateLimits { PerMinute = 10, PerHour = 100 } }, { "api-client-premium", new RateLimits { PerMinute = 100, PerHour = 1000 } } }, EndpointThrottling = true, EndpointRules = new Dictionary { { "api/search", new RateLimits { PerSecond = 10, PerMinute = 100 } }, { "api/upload", new RateLimits { PerMinute = 5, PerHour = 50 } } }, StackBlockedRequests = false }; ``` -------------------------------- ### XML Configuration for ThrottlePolicy Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Defines rate limiting policies using an XML configuration file (web.config or app.config) for flexible management without code changes. ```APIDOC ## XML Policy Configuration ### Description Allows defining complex rate limiting rules, whitelists, and global limits via the application configuration file. ### Method N/A (Configuration File) ### Endpoint N/A ### Parameters #### Request Body - **throttlePolicy** (XML Section) - Required - Configuration section containing limits, rules, and whitelists. - **rules** (Collection) - Optional - Specific limits for IP ranges, client keys, or endpoints. - **whitelists** (Collection) - Optional - Entities exempt from throttling. ### Request Example ### Response #### Success Response (200) - **Status** (Configuration Loaded) - Policy applied to the ThrottlingHandler. ``` -------------------------------- ### Endpoint Throttling based on IP and Client Key Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Configures throttling based on both IP address and a unique client API key for specific endpoints. ```APIDOC ## Endpoint Throttling based on IP and Client Key ### Description This setup enforces throttling limits that consider both the client's IP address and a unique API key. It allows for more granular control, especially in scenarios where multiple clients might share an IP address. If `IpThrottling` is set to `false`, limits are applied solely based on the client key. ### Method Not Applicable (Configuration via Message Handler) ### Endpoint Not Applicable (Applies to specific routes as configured) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cs config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository() }); ``` ### Response #### Success Response (200) Requests that adhere to both IP and client key throttling limits are processed. #### Response Example None (This is a configuration example) ### Error Handling Requests exceeding the combined IP and client key limits for a specific endpoint will receive a `429 Too Many Requests` status code. ``` -------------------------------- ### Configure Endpoint Throttling Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Applies rate limiting to specific API routes rather than global traffic. This ensures limits are scoped per endpoint. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository() }); ``` -------------------------------- ### Configure Endpoint Custom Rate Limits in C# Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md This code configures custom rate limits for specific API endpoints or URL segments. It allows defining rules based on relative routes or URL segments, and the engine applies the lower limit if multiple rules match a URI. Both IP and client throttling can be enabled alongside endpoint throttling. ```csharp config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200) { IpThrottling = true, ClientThrottling = true, EndpointThrottling = true, EndpointRules = new Dictionary { { "api/search", new RateLimits { PerSecond = 10, PerMinute = 100, PerHour = 1000 } } } }, Repository = new CacheRepository() }); ``` -------------------------------- ### Register ThrottlingHandler and Configure Policies Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Register the ThrottlingHandler in your Web API configuration, specifying custom repositories and initial rate limit policies. ```csharp public static void Register(HttpConfiguration config) { var traceWriter = new SystemDiagnosticsTraceWriter() { IsVerbose = true }; config.Services.Replace(typeof(ITraceWriter), traceWriter); config.EnableSystemDiagnosticsTracing(); config.MessageHandlers.Add(new ThrottlingHandler( policy: new ThrottlePolicy(perMinute: 20, perHour: 30, perDay: 35, perWeek: 3000) { IpThrottling = true, ClientThrottling = true, ClientRules = new Dictionary { { "api-client-key-1", new RateLimits { PerMinute = 60, PerHour = 600 } }, { "api-client-key-2", new RateLimits { PerDay = 5000 } } }, EndpointThrottling = true }, policyRepository: new PolicyCacheRepository(), repository: new CacheRepository(), logger: new TracingThrottleLogger(traceWriter))); } ``` -------------------------------- ### Customize Quota Exceeded Response Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Configures the ThrottlingHandler to return a custom HTTP status code and error message when rate limits are exceeded. ```csharp config.MessageHandlers.Add(new ThrottlingHandler( policy: new ThrottlePolicy(perMinute: 20, perHour: 30, perDay: 35, perWeek: 3000) { IpThrottling = true }, repository: new CacheRepository(), QuotaExceededResponseCode = HttpStatusCode.ServiceUnavailable, QuotaExceededMessage = "Too many calls! We can only allow {0} per {1}")); ``` -------------------------------- ### Configure ThrottlingFilter with ThrottlePolicy Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Registers the ThrottlingFilter in the Web API configuration, defining global rate limits, IP-based rules, client-based rules, and whitelists. ```csharp config.Filters.Add(new ThrottlingFilter() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200, perDay: 2000, perWeek: 10000) { IpThrottling = true, IpRules = new Dictionary { { "::1/10", new RateLimits { PerSecond = 2 } }, { "192.168.2.1", new RateLimits { PerMinute = 30, PerHour = 30*60, PerDay = 30*60*24 } } }, IpWhitelist = new List { "127.0.0.1", "192.168.0.0/24" }, ClientThrottling = true, ClientRules = new Dictionary { { "api-client-key-demo", new RateLimits { PerDay = 5000 } } }, ClientWhitelist = new List { "admin-key" }, EndpointThrottling = true } }); ``` -------------------------------- ### Endpoint Throttling based on IP Source: https://github.com/stefanprodan/webapithrottle/blob/master/README.md Applies throttling limits to specific API routes based on the originating IP address. ```APIDOC ## Endpoint Throttling based on IP ### Description This configuration limits requests on a per-endpoint basis for a given IP address. Calls to different routes from the same IP within the same second are allowed, but multiple calls to the same route will be throttled. ### Method Not Applicable (Configuration via Message Handler) ### Endpoint Not Applicable (Applies to specific routes as configured) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cs config.MessageHandlers.Add(new ThrottlingHandler() { Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30) { IpThrottling = true, EndpointThrottling = true }, Repository = new CacheRepository() }); ``` ### Response #### Success Response (200) Requests within the defined limits for the specific endpoint and IP are processed. #### Response Example None (This is a configuration example) ### Error Handling Requests exceeding the limits for a specific endpoint and IP will receive a `429 Too Many Requests` status code. ``` -------------------------------- ### Customize Rate Limit Exceeded Response in C# Source: https://context7.com/stefanprodan/webapithrottle/llms.txt Configures the ThrottlingHandler to return a custom HTTP status code and response message when rate limits are exceeded. It supports setting a specific status code, a formatted message, or a custom JSON content object. ```csharp public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ThrottlingHandler( policy: new ThrottlePolicy(perMinute: 20, perHour: 200) { IpThrottling = true, ClientThrottling = true }, policyRepository: null, repository: new CacheRepository(), logger: null) { // Return 503 Service Unavailable instead of 429 QuotaExceededResponseCode = HttpStatusCode.ServiceUnavailable, // Custom message with placeholders for limit and period QuotaExceededMessage = "Rate limit exceeded. Maximum {0} requests per {1}. Please wait and try again.", // Or return custom content object (serialized as JSON) QuotaExceededContent = (limit, period) => new { error = "rate_limit_exceeded", message = $"Too many requests. Limit: {limit} per {period}", retryAfter = period == RateLimitPeriod.Second ? 1 : period == RateLimitPeriod.Minute ? 60 : period == RateLimitPeriod.Hour ? 3600 : 86400 } }); } } // Response example when limit exceeded: // HTTP/1.1 429 Too Many Requests // Retry-After: 45 // Content-Type: application/json // // { // "error": "rate_limit_exceeded", // "message": "Too many requests. Limit: 20 per Minute", // "retryAfter": 60 // } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.