Eigenverft.Routed.RequestFilters 0.2.0.1-gbd73c3e2b5

This is a prerelease version of Eigenverft.Routed.RequestFilters.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Eigenverft.Routed.RequestFilters --version 0.2.0.1-gbd73c3e2b5
                    
NuGet\Install-Package Eigenverft.Routed.RequestFilters -Version 0.2.0.1-gbd73c3e2b5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Eigenverft.Routed.RequestFilters" Version="0.2.0.1-gbd73c3e2b5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Eigenverft.Routed.RequestFilters" Version="0.2.0.1-gbd73c3e2b5" />
                    
Directory.Packages.props
<PackageReference Include="Eigenverft.Routed.RequestFilters" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Eigenverft.Routed.RequestFilters --version 0.2.0.1-gbd73c3e2b5
                    
#r "nuget: Eigenverft.Routed.RequestFilters, 0.2.0.1-gbd73c3e2b5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Eigenverft.Routed.RequestFilters@0.2.0.1-gbd73c3e2b5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Eigenverft.Routed.RequestFilters&version=0.2.0.1-gbd73c3e2b5&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Eigenverft.Routed.RequestFilters&version=0.2.0.1-gbd73c3e2b5&prerelease
                    
Install as a Cake Tool

๐Ÿ›ก๏ธ Eigenverft.Routed.RequestFilters

NuGet Version NuGet Downloads Build Status Targets License

Composable request filtering, filter evaluation, enforcement, and filter-event storage for ASP.NET Core applications.

Important: This project is currently pre-1.0. Public APIs, option names, defaults, and configuration behavior may change between preview releases.

โœจ At a glance

Package Eigenverft.Routed.RequestFilters
Application model ASP.NET Core middleware and dependency-injection extensions
Target frameworks .NET 8 and .NET 10
Configuration IOptionsMonitor<T>, IConfiguration, or code-based delegates
Event storage Null, bounded in-memory, or SQLite
License MIT

The library is designed for applications that want to compose focused request policies instead of adopting one monolithic request-processing pipeline. Each component is registered explicitly and added to the pipeline explicitly.

๐Ÿงญ Contents

๐Ÿ“ฆ Installation

dotnet add package Eigenverft.Routed.RequestFilters

The package provides assets for:

  • net8.0
  • net10.0

It uses the ASP.NET Core shared framework.

๐Ÿš€ Quick start

Every middleware follows the same basic pattern:

  1. Register it with Add....
  2. Configure its matching and enforcement policy.
  3. Add it to the request pipeline with Use....

The following example allows only the configured host names.

Program.cs

using Eigenverft.Routed.RequestFilters.Middleware.HostNameFiltering;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHostNameFiltering();

var app = builder.Build();

app.UseHostNameFiltering();

app.MapGet("/", () => Results.Ok(new { status = "ready" }));

app.Run();

appsettings.json

{
  "HostNameFilteringOptions": {
    "Whitelist": [
      "api.example.com",
      "*.example.com"
    ],
    "Blacklist": [],
    "AllowBlacklistedRequests": false,
    "AllowUnmatchedRequests": false,
    "BlockStatusCode": 403
  }
}

The parameterless AddHostNameFiltering() registration binds the section named HostNameFilteringOptions. The example allows requests matching the whitelist and rejects unmatched or blacklisted hosts.

Caution: Registration alone is not an implicit deny policy. Many filters are intentionally observable by default. Set the relevant Allow... flags explicitly before relying on a filter for enforcement.

๐Ÿ” How filtering works

Most filtering middleware classifies an observed request value as one of three results:

Result Meaning
Whitelist The value matched an allowed pattern.
Blacklist The value matched a blocked pattern.
Unmatched The value matched neither list.

The corresponding options then determine whether the request is allowed, recorded, logged, or short-circuited with BlockStatusCode. When a value appears in both lists, FilterPriority controls which result wins.

Option names differ slightly between components, but the recurring controls are:

  • Whitelist and Blacklist
  • FilterPriority
  • AllowBlacklistedRequests
  • AllowUnmatchedRequests
  • RecordBlacklistedRequests
  • RecordUnmatchedRequests
  • per-result log levels
  • BlockStatusCode

Configuration forms

Most middleware components expose these registration forms:

// Bind the conventional XOptions configuration section.
builder.Services.AddHostNameFiltering();

// Bind configuration, then apply code-based overrides.
builder.Services.AddHostNameFiltering(options =>
{
    options.Whitelist = new() { "api.example.com" };
    options.AllowUnmatchedRequests = false;
});

// Bind from an explicitly supplied configuration root, then override values.
builder.Services.AddHostNameFiltering(
    builder.Configuration,
    options => options.BlockStatusCode = StatusCodes.Status403Forbidden);

Several middleware components also provide UseX(Action<XOptions>). That overload adds a pipeline-local configuration layer on top of the DI-registered options.

Configuration-bound middleware uses options monitoring. Reloadable configuration sources can therefore update values without rebuilding the middleware pipeline.

Pattern syntax

String-based filters use anchored wildcard patterns rather than raw regular expressions:

Token Meaning
* Zero or more characters
? Zero or one character
# Exactly one character

Examples:

Pattern Example match
*.example.com api.example.com
api-##.example.com api-01.example.com
/v?/health /v1/health and /v/health

Matching is anchored to the complete observed value. Matching is case-insensitive by default where the corresponding options expose a case-sensitivity switch.

๐Ÿงฉ Common recipes

Configure a filter entirely in code

using Eigenverft.Routed.RequestFilters.Middleware.HttpMethodFiltering;

builder.Services.AddHttpMethodFiltering(options =>
{
    options.Whitelist = new() { "GET", "HEAD" };
    options.AllowBlacklistedRequests = false;
    options.AllowUnmatchedRequests = false;
    options.BlockStatusCode = StatusCodes.Status405MethodNotAllowed;
});

Add the matching middleware before the endpoints it protects:

app.UseHttpMethodFiltering();
app.MapControllers();

Filter client IP addresses behind a reverse proxy

Configure trusted forwarded headers before remote-IP or CIDR filters. The host application remains responsible for defining trusted proxies and networks.

app.UseForwardedHeaders();
app.UseRemoteIpAddressFiltering();
app.UseCidrFiltering();

Never accept arbitrary forwarded headers from untrusted networks. Incorrect proxy trust configuration can make client-IP policies ineffective.

Record filter events and evaluate them later

using Eigenverft.Routed.RequestFilters.Middleware.FilteringEvaluationGate;
using Eigenverft.Routed.RequestFilters.Middleware.HostNameFiltering;
using Eigenverft.Routed.RequestFilters.Services.FilteringEvaluation.FilteringEvaluators;
using Eigenverft.Routed.RequestFilters.Services.FilteringEvent.FilteringStorage;

builder.Services.AddFilteringEventStorage<InMemoryStorage>();
builder.Services.AddFilteringEvaluator(FilteringEvaluatorKind.SimpleFilteringScore);
builder.Services.AddHostNameFiltering();
builder.Services.AddFilteringEvaluationGate();

var app = builder.Build();

app.UseHostNameFiltering();
app.UseFilteringEvaluationGate();

Use NullStorage when events should be discarded, InMemoryStorage for process-local bounded storage, or SqliteStorage when events must survive process restarts. Evaluator and storage selection use a last-call-wins model.

๐Ÿงฐ Middleware catalog

Request classification and filtering

Component Registration Pipeline Observed value
Accept language AddAcceptLanguageFiltering UseAcceptLanguageFiltering Accept-Language header
CIDR AddCidrFiltering UseCidrFiltering Remote address and CIDR networks
File extension AddFileExtensionBlocking UseFileExtensionBlocking Requested file extension
Host name AddHostNameFiltering UseHostNameFiltering Request host name
HTTP method AddHttpMethodFiltering UseHttpMethodFiltering GET, POST, and other methods
HTTP protocol AddHttpProtocolFiltering UseHttpProtocolFiltering HTTP protocol/version
Path depth AddPathDepthFiltering UsePathDepthFiltering Number of path segments
Remote IP AddRemoteIpAddressFiltering UseRemoteIpAddressFiltering Individual remote IP address
Request signature AddRequestSignatureFiltering UseRequestSignatureFiltering Composite request signature
Request URL AddRequestUrlFiltering UseRequestUrlFiltering Complete request URL
TLS protocol AddTlsProtocolFiltering UseTlsProtocolFiltering Negotiated TLS protocol
URI segment AddUriSegmentFiltering UseUriSegmentFiltering Individual path segments
User agent AddUserAgentFiltering UseUserAgentFiltering User-Agent header

Filter orchestration

Component Registration Pipeline Purpose
Browser bootstrap filtering AddBrowserBootstrapFiltering UseBrowserBootstrapFiltering Detect and control browser bootstrap requests.
Development unlocker AddDevelopmentUnlocker UseDevelopmentUnlocker Apply explicitly configured development unlock behavior.
Evaluation gate AddFilteringEvaluationGate UseFilteringEvaluationGate Enforce a filtering evaluator decision.

Each component has a dedicated namespace below:

Eigenverft.Routed.RequestFilters.Middleware.<ComponentName>

This keeps imports and registrations explicit and lets consumers include only the components they use.

๐Ÿ“Š Evaluation and event storage

Individual filters can emit FilteringEvent records. An evaluator can aggregate the events associated with an observed remote address and produce an allow/block decision for FilteringEvaluationGate.

Evaluators

Kind Behavior
NullFiltering Always uses the no-op evaluator.
SimpleFilteringScore Evaluates the accumulated filter score.
SourceAndMatchKindWeighted Applies configurable weights by event source and match kind.

Register exactly one active evaluator:

builder.Services.AddFilteringEvaluator(
    FilteringEvaluatorKind.SourceAndMatchKindWeighted);

Event storage

Selection Behavior
NullStorage Discards events.
InMemoryStorage Keeps a bounded process-local event history.
SqliteStorage Persists events in SQLite.

Register exactly one active storage:

builder.Services.AddFilteringEventStorage<SqliteStorage>();

Configurable backends bind their conventional sections:

  • InMemoryFilteringEventStorageOptions
  • InSqliteDbFilteringEventStorageOptions
  • SourceAndMatchKindWeightedFilteringEvaluatorOptions

FilteringEvaluationGate can enforce the evaluator result or run in allow-through mode. Allow-through mode is useful for observing a new policy before enabling blocking.

๐Ÿ”€ Pipeline ordering

Middleware order is part of the policy. A typical application should consider this sequence:

  1. Configure trusted forwarded headers when running behind a reverse proxy.
  2. Apply inexpensive request classifiers and filters.
  3. Apply FilteringEvaluationGate after the filters whose events it evaluates.
  4. Map application endpoints and resources after the filters that should protect them.

A minimal composed pipeline might look like this:

app.UseForwardedHeaders();
app.UseHostNameFiltering();
app.UseUserAgentFiltering();
app.UseFilteringEvaluationGate();

app.MapControllers();

Only include middleware that has been registered and configured for the application. Filters that need the peer address insert the shared ClientNetwork feature once; proxy trust and forwarded-header ordering remain the host application's responsibility.

๐Ÿงญ Scope boundary

Application hosting, Kestrel/SNI, certificates, configuration-source composition, startup logging, static-file serving, warm-up, health probes, canonical redirects, general request logging, and traffic shaping are intentionally outside this package. Applications that need those capabilities reference their dedicated WebLib or NetLib packages directly; they are not forwarded or transitively exposed by RequestFilters.

๐Ÿงช Build from source

git clone https://github.com/eigenverft/Eigenverft.Routed.RequestFilters.git
cd Eigenverft.Routed.RequestFilters

dotnet restore src/Eigenverft.Routed.RequestFilters.slnx
dotnet build src/Eigenverft.Routed.RequestFilters.slnx -c Release --no-restore

Create a local NuGet package with repository pack metadata enabled:

dotnet pack src/prj/Eigenverft.Routed.RequestFilters/Eigenverft.Routed.RequestFilters.csproj -c Release -p:Stage=pack

Main source layout:

src/
โ”œโ”€โ”€ Eigenverft.Routed.RequestFilters.slnx
โ””โ”€โ”€ prj/
    โ”œโ”€โ”€ Eigenverft.Routed.RequestFilters/
    โ”‚   โ”œโ”€โ”€ Middleware/
    โ”‚   โ””โ”€โ”€ Services/
    โ””โ”€โ”€ Eigenverft.Routed.RequestFilters.Tests/

๐Ÿ” Security notes

This library provides application middleware, not a complete web application firewall. Review every enabled filter, default, bypass, proxy, and logging setting for the deployment environment.

In particular:

  • configure enforcement flags explicitly;
  • verify trusted proxies before relying on client-IP information;
  • place filters before the endpoints or resources they protect;
  • start new evaluator policies in allow-through mode where practical;
  • do not expose development unlock behavior in production;
  • avoid logging secrets, credentials, or sensitive request data;
  • treat preview upgrades as potentially breaking until the project reaches 1.0.

๐Ÿšข Project status

Preview packages are produced by the repository's CI/CD workflow. Source, releases, and issue tracking are available in the GitHub repository.

๐Ÿ“„ License

Licensed under the MIT License by Eigenverft.


Made with โค๏ธ by Eigenverft

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0.2-ge4f9b3cdb4 0 9/22/2026
0.2.0.1-gbd73c3e2b5 0 9/21/2026

Next Release - Filter-only Capability Split (Unreleased)
=======================================================

This release narrows Eigenverft.Routed.RequestFilters to request filters,
filter policy and decisions, filter events, evaluation/enforcement, and
filter-owned event storage.

Breaking Changes
----------------
- Target frameworks are now .NET 8 and .NET 10. .NET 6 and .NET 7 assets are
 no longer produced.
- Removed application-hosting and configuration APIs: WebApplicationBuilderFactory,
 AppDirectoryLayout, SetDirectoryLayout/GetDirectoryLayout,
 AddDefaultConfigurationSources, encoded-settings APIs,
 configuration-precedence diagnostics, WritebackJsonStore, ProcessPath, and
 writable-directory helpers.
- Removed Kestrel/SNI and certificate APIs: ConfigureKestrelSni,
 ConfigureKestrelSniFromConfiguration, KestrelSniSettings,
 CertificateMappingSetting, CertificateManager, and their supporting enums
 and models.
- Removed static-file, warm-up, host/HTTPS, and startup-logging helpers:
 UseStaticFilesWithPwaAndBlazorContentTypes, AddPwaAndBlazorMappings,
 UseNonAssetFiles/UseDynamicNonAssetFiles, AddWarmUpRequests,
 AddAllowedHosts, AddPermanentHttpsRedirection, BootstrapLogger, and the
 Serilog/Microsoft/deferred logger bridge extensions.
- Removed non-filter middleware and options for CanonicalHostRedirect,
 HealthProbeFaviconAware, RequestLogging, RequestDelayThrottling, and
 RequestRateSmoothing.
- Removed shared local infrastructure APIs: RemoteIpAddressContextMiddleware,
 its HttpContext extensions, generic HttpContext.Items helpers,
 WriteDefaultStatusCodeAnswer/WriteDefaultStatusCodeAnswerEx,
 UseMiddlewareOnce, EnsureServicesRegistered, GetIpInfo and IP normalization,
 HttpStatusCodeDescriptions, ConfiguredOptionsMonitor, the public generic
 wildcard/regex extensions, and the local deferred-logger types and
 AddDeferredLogging.
- Filter option collection properties now use List<T>; the weighted evaluator's
 SourceFactors property now uses Dictionary<string, int>. The removed
 OptionsConfigOverridesDefaultsList and OptionsConfigOverridesDefaultsDictionary
 types are no longer part of the public API.
- FilterClassifier.Classify accepts IEnumerable<string> pattern collections
 instead of array-only parameters.

Retained Filter Capability Dependencies
---------------------------------------
- Eigenverft.WebLib.Middleware.Primitives supplies middleware registration,
 DI validation, use-site options, typed request features, and status responses.
- Eigenverft.WebLib.ClientNetwork supplies the peer-address feature used by
 filters that classify or record client addresses.
- Eigenverft.NetLib.Networking supplies IP normalization and CIDR matching.
- Eigenverft.NetLib.Configuration.Binding supplies explicit replacement binding
 for normal list/dictionary option properties. Missing or explicitly empty
 configured collections retain code defaults; non-empty collections replace
 them, including after reload.
- Eigenverft.NetLib.Logging.Deferred supplies lazy filter logging.

These dependencies support retained filter code only. Removed application
capabilities are not re-exported through RequestFilters. An application that
still needs hosting, Kestrel/SNI, certificates, configuration composition,
static files, warm-up, health probes, redirects, general request logging, or
traffic shaping must select and reference the corresponding narrow package
directly.

Validation
----------
- Release builds cover .NET 8 and .NET 10.
- 47 characterization tests on each target framework cover collection binding,
 pattern/CIDR/client-network behavior, activation of every retained filter,
 filter-event recording, EvaluationGate, DevelopmentUnlocker, and the
 Null/InMemory/SQLite event stores.

Release Notes โ€“ 0.1.* (2026-07-23)
===================================

Status: First Public Preview Release
------------------------------------
This is the first public NuGet release of Eigenverft.Routed.RequestFilters.
The package remains pre-1.0, so APIs and configuration may change as the
library evolves.

Highlights
----------
- ASP.NET Core middleware for request filtering, evaluation, enforcement, and
 filter-event storage.
- Narrow capability dependencies for networking, deferred logging,
 configuration binding, and middleware primitives.
- Multi-targeted package support for .NET 8 and .NET 10.
- Updated SQLite dependencies to avoid the known vulnerable native package.
- Package metadata, embedded README, icon, and MIT license declaration.

Release Channel
---------------
Production builds from the main branch are published to nuget.org.