Argon.Extensions.Hosting 8.5.0
Argon.Extensions.Hosting
Middlewares, endpoints, and extensions for ASP.NET Core applications.
📦 Installation
dotnet add package Argon.Extensions.Hosting
✨ Features
- StaticPathBaseMiddleware: Middleware to handle a static path base
- Health Checks Extensions: Advanced health checks endpoint mapping with host restrictions and path base support
- Configuration-based setup: Configure hosting features via
appsettings.json
🚀 Usage
StaticPathBaseMiddleware
This middleware ensures that all requests start with a specified path base. Requests that don't match the path base will receive a 404 response.
using Argon.Extensions.Hosting.Middlewares;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// Use a static path base
app.UseStaticPathBase("/api");
app.MapControllers();
app.Run();
What it does:
- Validates that incoming requests start with the specified path base
- Adds the path base to
HttpContext.Request.PathBase - Returns 404 for requests that don't match the path base
- Properly strips the path base from the remaining path
Example:
With app.UseStaticPathBase("/api"):
- ✅
/api/users→ PathBase:/api, Path:/users - ✅
/api/products/123→ PathBase:/api, Path:/products/123 - ❌
/users→ 404 Not Found
Health Checks Endpoints
This package provides advanced health checks endpoint mapping with support for:
- Custom path base
- Host requirements (restrict access to specific hosts/ports)
- Liveness and readiness probes
- UI-friendly response format
Basic Health Checks
using Argon.Extensions.Hosting;
using Argon.Extensions.Hosting.Endpoints;
using Argon.Extensions.Hosting.Abstractions.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Add health checks with configuration
var healthConfig = new HealthChecksConfiguration
{
PathBase = "/health",
HostRequirements = "*:9090" // Only accessible on port 9090
};
builder.Services.AddHealthChecks(healthConfig);
var app = builder.Build();
// Map default health checks endpoint at /health
app.MapHealthChecksDefault();
app.Run();
Liveness and Readiness Probes
using Argon.Extensions.Hosting;
using Argon.Extensions.Hosting.Endpoints;
using Argon.Extensions.Hosting.Abstractions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
var healthConfig = new HealthChecksConfiguration
{
PathBase = "/health"
};
builder.Services.AddHealthChecks(healthConfig)
.AddCheck("database", () => HealthCheckResult.Healthy(), tags: new[] { "ready" })
.AddCheck("external-api", () => HealthCheckResult.Healthy(), tags: new[] { "ready" });
var app = builder.Build();
// Liveness probe - always returns 200 if app is running
app.MapHealthChecksLiveness(); // GET /health/live
// Readiness probe - checks dependencies with "ready" tag
app.MapHealthChecksReady(); // GET /health/ready
app.Run();
Configuration-based Setup
Add to appsettings.json:
{
"Hosting": {
"HealthChecks": {
"PathBase": "/health",
"HostRequirements": "*:9090"
}
}
}
Then use in code:
using Argon.Extensions.Hosting;
using Argon.Extensions.Hosting.Endpoints;
using Argon.Extensions.Hosting.Abstractions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
// Bind configuration from appsettings.json
var healthConfig = builder.Configuration
.GetSection("Hosting:HealthChecks")
.Get<HealthChecksConfiguration>() ?? new HealthChecksConfiguration();
builder.Services.AddHealthChecks(healthConfig)
.AddCheck("self", () => HealthCheckResult.Healthy());
var app = builder.Build();
app.MapHealthChecksDefault();
app.MapHealthChecksLiveness();
app.MapHealthChecksReady();
app.Run();
Host Requirements
Default behavior: Health checks are restricted to port 9090 (*:9090). This is useful for:
- Separating monitoring traffic from application traffic
- Preventing public exposure of health endpoints
- Kubernetes/container health probes on dedicated ports
Important: The port validation uses the local port (Connection.LocalPort) instead of the port in the Host header. This means it works correctly with Docker port mapping and reverse proxies.
var config = new HealthChecksConfiguration
{
HostRequirements = "*:9090" // Any host on port 9090 (local port)
};
builder.Services.AddHealthChecks(config);
// Multiple patterns (OR logic - any match is accepted):
var multiConfig = new HealthChecksConfiguration
{
HostRequirements = "localhost:9090,monitoring.internal:9090"
};
builder.Services.AddHealthChecks(multiConfig);
// With scheme validation:
var httpsConfig = new HealthChecksConfiguration
{
HostRequirements = "https://*:9090" // Only HTTPS on port 9090
};
builder.Services.AddHealthChecks(httpsConfig);
// Wildcard subdomain:
var wildcardConfig = new HealthChecksConfiguration
{
HostRequirements = "*.example.com:9090" // Any subdomain of example.com on port 9090
};
builder.Services.AddHealthChecks(wildcardConfig);
// To make health checks publicly accessible (no restriction):
var publicConfig = new HealthChecksConfiguration
{
HostRequirements = "" // Empty string = no host requirement
};
builder.Services.AddHealthChecks(publicConfig);
Docker Port Mapping Support
When running behind Docker with port mapping (e.g., 9090:9005), the validation checks the internal local port (9005), not the external one:
var config = new HealthChecksConfiguration
{
PathBase = "/health",
HostRequirements = "*:9005" // Internal port inside the container
};
// In Docker Compose:
// ports:
// - "9090:9005" # External:Internal
Why this works:
- ✅ Checks
context.Connection.LocalPort(the real port: 9005) - ✅ Not affected by port mapping or reverse proxies
- ✅ More reliable than checking the Host header
Pattern Format
The HostRequirements property supports the same format as ASP.NET Core's RequireHost(), but validates against the local port:
| Pattern | Description | Example |
|---|---|---|
* |
Any host, any port | All requests accepted |
*:9090 |
Any host on port 9090 | Works with localhost:9090, 192.168.1.1:9090 |
localhost |
localhost on any port | Only localhost |
localhost:9090 |
localhost on port 9090 | Specific host and port |
*.example.com:9090 |
Any subdomain on port 9090 | api.example.com:9090, www.example.com:9090 |
https://*:9090 |
Any host on port 9090 via HTTPS | Validates scheme too |
host1:9090,host2:9091 |
Multiple patterns (OR) | Either pattern matches |
Configuration via appsettings.json:
{
"Hosting": {
"HealthChecks": {
"PathBase": "/health",
"HostRequirements": "*:9005"
}
}
}
📝 API Reference
Dependency Injection Extensions
AddHealthChecks
public static IHealthChecksBuilder AddHealthChecks(
this IServiceCollection services,
HealthChecksConfiguration configuration)
Adds health checks services with the specified configuration. The configuration is registered as IOptions<HealthChecksConfiguration> and used by the mapping extensions.
Parameters:
services: The service collectionconfiguration: Health checks configuration (PathBase, HostRequirements)
Returns: An IHealthChecksBuilder to add health check registrations
Middleware Extensions
UseStaticPathBase
public static IApplicationBuilder UseStaticPathBase(
this IApplicationBuilder app,
PathString pathBase)
Adds the StaticPathBaseMiddleware to the application pipeline.
Parameters:
app: The application builderpathBase: The path base to extract (must not be empty)
Returns: The application builder for method chaining
Exceptions:
ArgumentNullException: Ifappis nullArgumentException: IfpathBaseis null or empty
Health Checks Endpoint Extensions
All health checks endpoint methods retrieve the configuration from IOptions<HealthChecksConfiguration> that was registered via AddHealthChecks().
Default Configuration Values:
PathBase:/healthHostRequirements:*:9090(restricts access to port 9090 by default)
To use different values, either:
- Pass a custom
HealthChecksConfigurationtoAddHealthChecks() - Configure via
appsettings.json(see Configuration-based Setup section)
MapHealthChecksDefault
public static IEndpointConventionBuilder MapHealthChecksDefault(
this IEndpointRouteBuilder endpoints,
string? pattern = null,
Action<HealthCheckOptions>? configureOptions = null)
Maps a default health checks endpoint with UI-friendly response format.
Parameters:
endpoints: The endpoint route builderpattern: Optional URL pattern (combined with PathBase from configuration). Defaults to empty string.configureOptions: Optional configuration for HealthCheckOptions
Returns: An IEndpointConventionBuilder for further configuration
MapHealthChecksLiveness
public static IEndpointConventionBuilder MapHealthChecksLiveness(
this IEndpointRouteBuilder endpoints,
string pattern = "/live",
Action<HealthCheckOptions>? configureOptions = null)
Maps a liveness probe endpoint. Always returns healthy if the application is running (uses predicate _ => false to skip all checks).
Parameters:
endpoints: The endpoint route builderpattern: URL pattern (combined with PathBase from configuration). Defaults to/live.configureOptions: Optional configuration for HealthCheckOptions
Returns: An IEndpointConventionBuilder for further configuration
Default pattern: /live
MapHealthChecksReady
public static IEndpointConventionBuilder MapHealthChecksReady(
this IEndpointRouteBuilder endpoints,
string pattern = "/ready",
Action<HealthCheckOptions>? configureOptions = null)
Maps a readiness probe endpoint. Only runs health checks tagged with "ready".
Parameters:
endpoints: The endpoint route builderpattern: URL pattern (combined with PathBase from configuration). Defaults to/ready.configureOptions: Optional configuration for HealthCheckOptions
Returns: An IEndpointConventionBuilder for further configuration
Default pattern: /ready
🔗 Links
No packages depend on Argon.Extensions.Hosting.
.NET 8.0
- Argon.Extensions.Hosting.Abstractions (>= 8.5.0)
- AspNetCore.HealthChecks.UI.Client (>= 8.0.1)