Forwarded Headers overview
DamianH.Http.ForwardedHeaders provides standalone
RFC 7239 Forwarded
header parsing and trusted-proxy middleware for ASP.NET Core on .NET 10.
ASP.NET Core's built-in UseForwardedHeaders reads X-Forwarded-*, not RFC 7239.
This library processes Forwarded directly, keeping each hop's parameters
together. It is not a legacy-header adapter and never translates, merges,
prefers, or falls back to X-Forwarded-*. RFC 7239 is not an RFC 8941 Structured
Field; this package does not depend on the StructuredFieldValues library.
Installation
Run in the consuming project directory:
dotnet add package DamianH.Http.ForwardedHeadersThe parser and middleware ship in the same package, which has a
Microsoft.AspNetCore.App framework reference. Even a parser-only application
requires the ASP.NET Core runtime. There is no public serializer in v1.
One local proxy: quick start
using DamianH.Http.ForwardedHeaders;
using Microsoft.AspNetCore.Http.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddForwarded(options =>
{
options.Parameters = ForwardedParameters.For | ForwardedParameters.Host
| ForwardedParameters.Proto;
options.ForwardLimit = 1;
// Retain the defaults: KnownProxies = ::1, KnownIPNetworks = 127.0.0.0/8.
options.AllowedHosts.Add("localhost");
});
var app = builder.Build();
app.UseForwarded();
app.UseRouting();
app.MapGet("/request", (HttpRequest request) => request.GetEncodedUrl());
app.Run();Use this trust configuration only for a local proxy and control direct client
access. Register forwarding early, before routing, HTTPS redirection,
authentication, authorization, and anything that generates external URLs.
AddForwarded uses the options system and validates at startup; middleware
snapshots its configuration. Alternatively, use
app.UseForwarded(new ForwardedOptions { Parameters = ForwardedParameters.Proto })
with explicitly configured trust for your deployment. Do not register both forms.
Before deployment, read proxy configuration
and deployment safety, especially
trust-all behavior and incompatibility with UseForwardedHeaders on the same
request. PathBase is a separate, nonstandard
opt-in; diagnostics describes malformed
input handling and trusted observations.
Run the sample
The ASP.NET Core sample enables
For | Host | Proto | PathBase, trusts the loopback defaults, accepts one hop,
and allowlists localhost. From the repository root:
dotnet run --project forwarded-headers\samples\AspNetCoreSample --urls http://127.0.0.1:5080In another PowerShell 7.3+ window (with standard native argument passing),
simulate a local proxy using curl.exe:
curl.exe -H 'Forwarded: for=192.0.2.60;host="localhost:8443";proto=https;pathbase="/gateway"' http://127.0.0.1:5080/requestThe response URL is https://localhost:8443/gateway/request, with effective
remote IP 192.0.2.60 and port 0. The actual endpoint path remains /request.
The sample returns neither the raw header nor the proxy chain.
Build or test this product using the shared repository build helpers, from the repository root:
dotnet run forwarded-headers\build.cs -- build
dotnet run forwarded-headers\build.cs -- testFor parsing without middleware, see direct parser use.