diff --git a/src/OrchardCoreContrib.Garnet/README.md b/src/OrchardCoreContrib.Garnet/README.md
index 8f955e8..d76e138 100644
--- a/src/OrchardCoreContrib.Garnet/README.md
+++ b/src/OrchardCoreContrib.Garnet/README.md
@@ -70,22 +70,22 @@ This module has no dependencies.
2. Go to the admin site
3. Select **Configuration -> Features** menu.
-## Garnet
+#### Garnet
4. Enable the `Garnet` feature.
-## Garnet Cache
+#### Garnet Cache
4. Enable the `Garnet Cache` feature.
-## Garnet Bus
+#### Garnet Bus
4. Enable the `Garnet Bus` feature.
-## Garnet DataProtection
+#### Garnet DataProtection
4. Enable the `Garnet DataProtection` feature.
-## Garnet Lock
+#### Garnet Lock
4. Enable the `Garnet Lock` feature.
diff --git a/src/OrchardCoreContrib.HealthChecks/Constants.cs b/src/OrchardCoreContrib.HealthChecks/Constants.cs
index ea6d488..233cabd 100644
--- a/src/OrchardCoreContrib.HealthChecks/Constants.cs
+++ b/src/OrchardCoreContrib.HealthChecks/Constants.cs
@@ -2,5 +2,16 @@
public class Constants
{
- public const string ConfigurationKey = "OrchardCoreContrib_HealthChecks";
+ ///
+ /// Defines the configuration key for health checks settings in the Orchard Core configuration system.
+ ///
+ public const string HealthChecksConfigurationKey = "OrchardCoreContrib_HealthChecks";
+ ///
+ /// Defines the configuration key for health checks access settings in the Orchard Core configuration system.
+ ///
+ public const string HealthChecksAccessConfigurationKey = "OrchardCoreContrib_HealthChecks:Access";
+ ///
+ /// Defines the configuration key for health checks rate limiting settings in the Orchard Core configuration system.
+ ///
+ public const string HealthChecksRateLimitingConfigurationKey = "OrchardCoreContrib_HealthChecks:RateLimiting";
}
diff --git a/src/OrchardCoreContrib.HealthChecks/HealthChecksAccessOptions.cs b/src/OrchardCoreContrib.HealthChecks/HealthChecksAccessOptions.cs
index 025d8b2..c77775b 100644
--- a/src/OrchardCoreContrib.HealthChecks/HealthChecksAccessOptions.cs
+++ b/src/OrchardCoreContrib.HealthChecks/HealthChecksAccessOptions.cs
@@ -1,6 +1,12 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Provides configuration options for controlling access to health check endpoints, such as allowed IP addresses.
+///
public class HealthChecksAccessOptions
{
+ ///
+ /// Gets or sets the collection of IP addresses that are permitted access.
+ ///
public HashSet AllowedIPs { get; set; } = [];
}
diff --git a/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingMiddleware.cs b/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingMiddleware.cs
index c3817dc..3744ea8 100644
--- a/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingMiddleware.cs
+++ b/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingMiddleware.cs
@@ -6,6 +6,9 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Middleware that enforces rate limiting and temporary blocking for health check endpoints based on client IP address.
+///
public class HealthChecksBlockingRateLimitingMiddleware
{
private static readonly ConcurrentDictionary _blockedIPs = new();
@@ -39,6 +42,7 @@ public HealthChecksBlockingRateLimitingMiddleware(
});
}
+ ///
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path.Equals(_healthChecksOptions.Url))
diff --git a/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingOptions.cs b/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingOptions.cs
index 1524d12..782ca65 100644
--- a/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingOptions.cs
+++ b/src/OrchardCoreContrib.HealthChecks/HealthChecksBlockingRateLimitingOptions.cs
@@ -1,6 +1,12 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Provides configuration options for blocking rate limiting applied to health check endpoints.
+///
public class HealthChecksBlockingRateLimitingOptions : HealthChecksRateLimitingOptions
{
+ ///
+ /// Gets or sets the duration for which a client is blocked when the rate limit is exceeded. Defaults to 1 minute.
+ ///
public TimeSpan BlockDuration { get; set; } = TimeSpan.FromMinutes(1);
}
diff --git a/src/OrchardCoreContrib.HealthChecks/HealthChecksIPRestrictionMiddleware.cs b/src/OrchardCoreContrib.HealthChecks/HealthChecksIPRestrictionMiddleware.cs
index 5b74ae2..371272f 100644
--- a/src/OrchardCoreContrib.HealthChecks/HealthChecksIPRestrictionMiddleware.cs
+++ b/src/OrchardCoreContrib.HealthChecks/HealthChecksIPRestrictionMiddleware.cs
@@ -4,6 +4,13 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Middleware that restricts access to health check endpoints based on allowed IP addresses.
+///
+/// The representing the next middleware in the pipeline.
+/// The containing health check configuration.
+/// The containing IP access configuration.
+/// The used for logging.
public class HealthChecksIPRestrictionMiddleware(
RequestDelegate next,
IOptions healthChecksOptions,
@@ -12,6 +19,7 @@ public class HealthChecksIPRestrictionMiddleware(
{
private readonly HealthChecksOptions _healthChecksOptions = healthChecksOptions.Value;
+ ///
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path.Equals(_healthChecksOptions.Url))
diff --git a/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingMiddleware.cs b/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingMiddleware.cs
index f9ebb8c..d7cc499 100644
--- a/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingMiddleware.cs
+++ b/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingMiddleware.cs
@@ -5,6 +5,9 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Middleware that enforces rate limiting on health check endpoints to prevent excessive requests.
+///
public class HealthChecksRateLimitingMiddleware
{
private readonly RequestDelegate _next;
@@ -33,6 +36,7 @@ public HealthChecksRateLimitingMiddleware(
});
}
+ ///
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path.Equals(_healthChecksOptions.Url))
diff --git a/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingOptions.cs b/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingOptions.cs
index d0ce9bf..59eeb1a 100644
--- a/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingOptions.cs
+++ b/src/OrchardCoreContrib.HealthChecks/HealthChecksRateLimitingOptions.cs
@@ -1,13 +1,28 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Provides configuration options for rate limiting applied to health check endpoints.
+///
public class HealthChecksRateLimitingOptions
{
+ ///
+ /// Gets or sets the maximum number of concurrent permits that can be acquired. Defaults to 5.
+ ///
public int PermitLimit { get; set; } = 5;
+ ///
+ /// Gets or sets the time window for which the rate limiting is applied. Defaults to 10 seconds.
+ ///
public TimeSpan Window { get; set; } = TimeSpan.FromSeconds(10);
+ ///
+ /// Gets or sets the number of segments the time window is divided into for rate limiting purposes. Defaults to 10.
+ ///
public int SegmentsPerWindow { get; set; } = 10;
+ ///
+ /// Gets or sets the maximum number of requests that can be queued when the rate limit is exceeded. Defaults to 0.
+ ///
public int QueueLimit { get; set; } = 0;
}
diff --git a/src/OrchardCoreContrib.HealthChecks/Startups/BlockingRateLimitingStartup.cs b/src/OrchardCoreContrib.HealthChecks/Startups/BlockingRateLimitingStartup.cs
new file mode 100644
index 0000000..3048721
--- /dev/null
+++ b/src/OrchardCoreContrib.HealthChecks/Startups/BlockingRateLimitingStartup.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCore.Environment.Shell.Configuration;
+using OrchardCore.Modules;
+
+namespace OrchardCoreContrib.HealthChecks;
+
+///
+/// Configures blocking rate limiting for health check endpoints during application startup.
+///
+/// The .
+[Feature("OrchardCoreContrib.HealthChecks.BlockingRateLimiting")]
+public class BlockingRateLimitingStartup(IShellConfiguration shellConfiguration) : StartupBase
+{
+ ///
+ public override int Order => 20;
+
+ ///
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ var rateLimitingSection = shellConfiguration.GetSection(Constants.HealthChecksRateLimitingConfigurationKey);
+
+ services.Configure(rateLimitingSection);
+ services.Configure(rateLimitingSection);
+ }
+
+ ///
+ public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
+ => app.UseMiddleware();
+}
diff --git a/src/OrchardCoreContrib.HealthChecks/Startups/IPRestrictionStartup.cs b/src/OrchardCoreContrib.HealthChecks/Startups/IPRestrictionStartup.cs
new file mode 100644
index 0000000..c9ae3d8
--- /dev/null
+++ b/src/OrchardCoreContrib.HealthChecks/Startups/IPRestrictionStartup.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCore.Environment.Shell.Configuration;
+using OrchardCore.Modules;
+
+namespace OrchardCoreContrib.HealthChecks;
+
+///
+/// Configures IP-based access restrictions for health check endpoints during application startup.
+///
+/// The .
+[Feature("OrchardCoreContrib.HealthChecks.IPRestriction")]
+public class IPRestrictionStartup(IShellConfiguration shellConfiguration) : StartupBase
+{
+ ///
+ public override int Order => 10;
+
+ ///
+ public override void ConfigureServices(IServiceCollection services)
+ => services.Configure(shellConfiguration.GetSection(Constants.HealthChecksAccessConfigurationKey));
+
+ ///
+ public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
+ => app.UseMiddleware();
+}
diff --git a/src/OrchardCoreContrib.HealthChecks/Startups/RateLimitingStartup.cs b/src/OrchardCoreContrib.HealthChecks/Startups/RateLimitingStartup.cs
new file mode 100644
index 0000000..abede72
--- /dev/null
+++ b/src/OrchardCoreContrib.HealthChecks/Startups/RateLimitingStartup.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCore.Environment.Shell.Configuration;
+using OrchardCore.Modules;
+
+namespace OrchardCoreContrib.HealthChecks;
+
+///
+/// Configures rate limiting for health check endpoints during application startup.
+///
+/// The .
+[Feature("OrchardCoreContrib.HealthChecks.RateLimiting")]
+public class RateLimitingStartup(IShellConfiguration shellConfiguration) : StartupBase
+{
+ ///
+ public override int Order => 30;
+
+ ///
+ public override void ConfigureServices(IServiceCollection services)
+ => services.Configure(shellConfiguration.GetSection(Constants.HealthChecksRateLimitingConfigurationKey));
+
+ ///
+ public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
+ => app.UseMiddleware();
+}
diff --git a/src/OrchardCoreContrib.HealthChecks/Startup.cs b/src/OrchardCoreContrib.HealthChecks/Startups/Startup.cs
similarity index 55%
rename from src/OrchardCoreContrib.HealthChecks/Startup.cs
rename to src/OrchardCoreContrib.HealthChecks/Startups/Startup.cs
index 4d1f89b..04d3d06 100644
--- a/src/OrchardCoreContrib.HealthChecks/Startup.cs
+++ b/src/OrchardCoreContrib.HealthChecks/Startups/Startup.cs
@@ -13,17 +13,23 @@
namespace OrchardCoreContrib.HealthChecks;
+///
+/// Configures health check endpoints during application startup.
+///
+/// The .
public class Startup(IShellConfiguration shellConfiguration) : StartupBase
{
private static readonly JsonSerializerOptions _jsonSerializerOptions = new() { WriteIndented = true };
+ ///
public override void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
- services.Configure(shellConfiguration.GetSection(Constants.ConfigurationKey));
+ services.Configure(shellConfiguration.GetSection(Constants.HealthChecksConfigurationKey));
}
+ ///
public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
{
var healthChecksOptions = serviceProvider.GetService>().Value;
@@ -67,45 +73,3 @@ private static async Task WriteResponse(HttpContext context, HealthReport report
await context.Response.WriteAsync(JsonSerializer.Serialize(response, response.GetType(), options: _jsonSerializerOptions));
}
}
-
-[Feature("OrchardCoreContrib.HealthChecks.IPRestriction")]
-public class IPRestrictionStartup(IShellConfiguration shellConfiguration) : StartupBase
-{
- public override int Order => 10;
-
- public override void ConfigureServices(IServiceCollection services)
- => services.Configure(shellConfiguration.GetSection($"{Constants.ConfigurationKey}:Access"));
-
- public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
- => app.UseMiddleware();
-}
-
-[Feature("OrchardCoreContrib.HealthChecks.RateLimiting")]
-public class RateLimitingStartup(IShellConfiguration shellConfiguration) : StartupBase
-{
- public override int Order => 30;
-
- public override void ConfigureServices(IServiceCollection services)
- => services.Configure(shellConfiguration.GetSection($"{Constants.ConfigurationKey}:RateLimiting"));
-
- public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
- => app.UseMiddleware();
-}
-
-[Feature("OrchardCoreContrib.HealthChecks.BlockingRateLimiting")]
-public class BlockingRateLimitingStartup(IShellConfiguration shellConfiguration) : StartupBase
-{
- public override int Order => 20;
-
- public override void ConfigureServices(IServiceCollection services)
- {
- var rateLimitingSection = shellConfiguration.GetSection($"{Constants.ConfigurationKey}:RateLimiting");
-
- services.Configure(rateLimitingSection);
- services.Configure(rateLimitingSection);
- }
-
- public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
- => app.UseMiddleware();
-}
-
diff --git a/test/OrchardCoreContrib.HealthChecks.Tests/OrchardCoreStartup.cs b/test/OrchardCoreContrib.HealthChecks.Tests/OrchardCoreStartup.cs
index 4e7a79d..f715af0 100644
--- a/test/OrchardCoreContrib.HealthChecks.Tests/OrchardCoreStartup.cs
+++ b/test/OrchardCoreContrib.HealthChecks.Tests/OrchardCoreStartup.cs
@@ -48,9 +48,9 @@ private IConfigurationRoot AddHealthChecksConfiguration()
{
var newConfiguration = new Dictionary
{
- { $"{Constants.ConfigurationKey}:{nameof(HealthChecksOptions.Url)}", "/health" },
- { $"{Constants.ConfigurationKey}:Access:AllowedIPs:0", "127.0.0.1" },
- { $"{Constants.ConfigurationKey}:Access:AllowedIPs:1", "::1" }
+ { $"{Constants.HealthChecksConfigurationKey}:{nameof(HealthChecksOptions.Url)}", "/health" },
+ { $"{Constants.HealthChecksAccessConfigurationKey}:AllowedIPs:0", "127.0.0.1" },
+ { $"{Constants.HealthChecksAccessConfigurationKey}:AllowedIPs:1", "::1" }
};
return new ConfigurationBuilder()