IISModuleAPIRateLimiter 1.0.1
See the version list below for details.
dotnet add package IISModuleAPIRateLimiter --version 1.0.1
NuGet\Install-Package IISModuleAPIRateLimiter -Version 1.0.1
<PackageReference Include="IISModuleAPIRateLimiter" Version="1.0.1" />
<PackageVersion Include="IISModuleAPIRateLimiter" Version="1.0.1" />
<PackageReference Include="IISModuleAPIRateLimiter" />
paket add IISModuleAPIRateLimiter --version 1.0.1
#r "nuget: IISModuleAPIRateLimiter, 1.0.1"
#:package IISModuleAPIRateLimiter@1.0.1
#addin nuget:?package=IISModuleAPIRateLimiter&version=1.0.1
#tool nuget:?package=IISModuleAPIRateLimiter&version=1.0.1
IIS Module API Rate Limiter
A custom IIS HTTP Module for external-system-wise and API-wise rate limiting. Perfect for APIs that use custom authentication headers to identify external systems/clients.
Features
- ✅ External System-based Rate Limiting - Different limits per external system/client
- ✅ API-wise Rate Limiting - Different limits per endpoint
- ✅ Configurable Header Parsing - Extract external system from any header format
- ✅ URL Pattern Matching - Wildcards support (
*for segment,**for any path) - ✅ HTTP Method Filtering - Different limits for GET vs POST
- ✅ Sliding Window Algorithm - Smooth rate limiting without sharp resets
- ✅ Hot Reload - Config changes without IIS restart
- ✅ Thread-Safe - Handles parallel requests correctly
- ✅ Compatible - .NET Framework 4.5 and above
Installation
Via NuGet Package Manager
Install-Package IISModuleAPIRateLimiter -Version 1.0.0
Via .NET CLI
dotnet add package IISModuleAPIRateLimiter --version 1.0.0
Via Package Manager Console
PM> Install-Package IISModuleAPIRateLimiter
Quick Start
Step 1: Register Module in web.config
Add this to your application's web.config:
<configuration>
<system.webServer>
<modules>
<add name="ExternalSystemRateLimitingModule"
type="RateLimiter.IISModule.ExternalSystemRateLimitingModule, RateLimiter.IISModule"
preCondition="managedHandler" />
</modules>
</system.webServer>
</configuration>
Step 2: Create Configuration File
Create App_Data\ratelimit.externalsystem.config.json:
{
"enabled": true,
"applicationPathPrefix": "",
"authHeaderName": "Authorization",
"authHeaderPrefix": "Bearer ",
"authHeaderDelimiter": ":",
"externalSystemIndex": 3,
"defaultLimit": {
"maxRequests": 100,
"windowSeconds": 60
},
"globalApiRules": [
{
"name": "All APIs",
"urlPattern": "/api/**",
"maxRequests": 100,
"windowSeconds": 60
}
],
"externalSystemRules": {
"MyExternalSystem": {
"defaultLimit": {
"maxRequests": 100,
"windowSeconds": 60
},
"apiRules": [
{
"name": "MyExternalSystem APIs",
"urlPattern": "/api/**",
"maxRequests": 5,
"windowSeconds": 1
}
]
}
},
"whitelistedExternalSystems": ["InternalMonitoring"],
"excludedPaths": ["/health"]
}
Step 3: Configure Authorization Header
The module extracts the external system from your Authorization header.
Default format:
Authorization: Bearer token:signature:id:EXTERNAL_SYSTEM:timestamp
Example:
Authorization: Bearer abc123:xyz789:id001:MyExternalSystem:1767956650
The 4th value (MyExternalSystem) is used for rate limiting.
Step 4: Restart IIS
iisreset
Configuration Guide
Header Parsing Configuration
| Field | Description | Default |
|---|---|---|
authHeaderName |
Header name to read | "Authorization" |
authHeaderPrefix |
Prefix to remove (include space!) | "Bearer " |
authHeaderDelimiter |
Delimiter to split values | ":" |
externalSystemIndex |
0-based index of external system | 3 |
Example Configurations:
// Example 1: Default Bearer format
{
"authHeaderPrefix": "Bearer ",
"authHeaderDelimiter": ":",
"externalSystemIndex": 3
}
// Header: Bearer token:signature:id:MySystem:timestamp
// Result: External System = "MySystem"
// Example 2: Pipe delimiter
{
"authHeaderPrefix": "Bearer ",
"authHeaderDelimiter": "|",
"externalSystemIndex": 1
}
// Header: Bearer abc123|MySystem|user1
// Result: External System = "MySystem"
// Example 3: Custom header
{
"authHeaderName": "X-API-Key",
"authHeaderPrefix": "",
"authHeaderDelimiter": "",
"externalSystemIndex": 0
}
// Header: X-API-Key: MySystem
// Result: External System = "MySystem"
Rate Limit Configuration
Global Default Limit
{
"defaultLimit": {
"maxRequests": 100,
"windowSeconds": 60
}
}
Global API Rules (Applied to All External Systems)
{
"globalApiRules": [
{
"name": "Invoice API",
"urlPattern": "/api/v3/external/service/invoice",
"methods": ["GET"],
"maxRequests": 50,
"windowSeconds": 60,
"priority": 100
}
]
}
External System-Specific Rules
{
"externalSystemRules": {
"MobileApp": {
"defaultLimit": {
"maxRequests": 50,
"windowSeconds": 60
},
"apiRules": [
{
"name": "MobileApp Invoice API",
"urlPattern": "/api/v3/external/service/invoice",
"maxRequests": 20,
"windowSeconds": 60,
"priority": 100
}
]
},
"WebPortal": {
"defaultLimit": {
"maxRequests": 200,
"windowSeconds": 60
}
}
}
}
URL Pattern Examples
| Pattern | Matches |
|---|---|
/api/v3/external/service/invoice |
Exact match |
/api/v3/external/service/* |
Any endpoint under service |
/api/v3/external/** |
Any path under external |
/api/** |
Any API |
Whitelisting External Systems
{
"whitelistedExternalSystems": [
"InternalMonitoring",
"HealthCheck",
"AdminConsole"
]
}
Excluding Paths
{
"excludedPaths": [
"/health",
"/api/health",
"/favicon.ico"
]
}
Response Headers
Every response includes rate limit information:
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
X-RateLimit-Window: 1s
Rate Limit Exceeded Response
Status: 429 Too Many Requests
Headers:
Retry-After: 60
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Window: 1s
Body:
{
"error": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded for external system 'MyExternalSystem' on API '/api/users'.",
"details": {
"externalSystem": "MyExternalSystem",
"api": "/api/users",
"limit": 5,
"windowSeconds": 1,
"retryAfter": 1
}
}
Configuration Priority
Rate limits are applied in this order (first match wins):
- ✅ Whitelisted External Systems - Bypass rate limiting
- ✅ Excluded Paths - Bypass rate limiting
- ✅ External System-Specific API Rule - Highest priority
- ✅ External System Default Limit
- ✅ Global API Rule
- ✅ Global Default Limit - Fallback
Hot Reload
Configuration changes are automatically reloaded - no IIS restart needed! Just edit and save ratelimit.externalsystem.config.json.
Example Use Cases
Different Limits per External System
{
"externalSystemRules": {
"MobileApp": {
"defaultLimit": { "maxRequests": 50, "windowSeconds": 60 }
},
"WebPortal": {
"defaultLimit": { "maxRequests": 200, "windowSeconds": 60 }
},
"ThirdParty": {
"defaultLimit": { "maxRequests": 30, "windowSeconds": 60 }
}
}
}
Strict Limits for Specific APIs
{
"globalApiRules": [
{
"name": "Export API - Strict",
"urlPattern": "/api/v3/external/service/export",
"methods": ["GET"],
"maxRequests": 5,
"windowSeconds": 300,
"priority": 200
}
]
}
Override Global Rule for Specific External System
{
"globalApiRules": [
{
"name": "Invoice - Global",
"urlPattern": "/api/v3/external/service/invoice",
"maxRequests": 50,
"windowSeconds": 60
}
],
"externalSystemRules": {
"PremiumPartner": {
"apiRules": [
{
"name": "Invoice - Premium Override",
"urlPattern": "/api/v3/external/service/invoice",
"maxRequests": 500,
"windowSeconds": 60,
"priority": 100
}
]
}
}
}
Troubleshooting
Module Not Loading
- ✅ Verify DLLs are in
binfolder (installed via NuGet automatically) - ✅ Check Application Pool uses .NET 4.0 CLR
- ✅ Check Application Pool uses Integrated mode
- ✅ Verify module is registered in
web.config
Rate Limiting Not Working
- ✅ Verify module is registered in
web.config - ✅ Check if external system is whitelisted
- ✅ Verify Authorization header format matches config
- ✅ Check
ratelimit.externalsystem.config.jsonexists inApp_Datafolder - ✅ Verify JSON syntax is valid
Config Changes Not Applying
- ✅ Check JSON syntax is valid
- ✅ Verify IIS has read permission on
App_Datafolder - ✅ Check file is saved as
ratelimit.externalsystem.config.json
500 Internal Server Error
- ✅ Check Windows Event Viewer for details
- ✅ Verify
web.configsyntax is correct - ✅ Ensure all dependencies are installed (Newtonsoft.Json)
Performance
- ✅ In-memory sliding window algorithm (fast)
- ✅ Automatic cleanup of expired entries
- ✅ Thread-safe concurrent dictionary
- ✅ Minimal overhead (~1ms per request)
Requirements
- .NET Framework 4.5 or higher
- IIS 7.0 or higher
- Integrated Pipeline Mode
License
MIT License - Free to use, modify, and distribute.
Copyright (c) 2025 Dotnet Juggernaut
Support
For issues or questions:
- Check Windows Event Viewer logs
- Review the configuration file for typos
- Verify Authorization header format matches configuration
NuGet Package
📦 Package ID: IISModuleAPIRateLimiter
🔗 NuGet: https://www.nuget.org/packages/IISModuleAPIRateLimiter
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net45 is compatible. net451 is compatible. net452 is compatible. net46 is compatible. net461 is compatible. net462 is compatible. net463 was computed. net47 is compatible. net471 is compatible. net472 is compatible. net48 is compatible. net481 was computed. |
-
.NETFramework 4.5
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.5.1
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.5.2
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.6
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.6.1
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.6.2
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.7
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.7.1
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.7.2
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
-
.NETFramework 4.8
- Newtonsoft.Json (>= 13.0.1)
- System.ValueTuple (>= 4.5.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.