-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Background and Motivation
I've found myself in a situation where I needed endpoints responding on different ports. Mainly one for public requests and another for internal requests (health checks for example). To do this I resorted to the .RequireHost extension method and did something similar to this
app.MapHealthChecks( "/healthz" )
.RequireHost( "*:9001" )
.AllowAnonymous();
app.MapGet( "/", () =>
{
// ...
} )
.RequireHost( "*:8080" );
Locally things work properly and so I was surprised when deployed behind a reverse proxy I wasn't able to reach the public endpoint, but was able to reach the health check (internally).
Turns out that RequireHost uses the Host header, which behind a reverse proxy that may be the public host/port and not the one we're listening to. It took me a while to figure this out and it also took me quite a while to figure out how to create a filter to look at the HttpContext.Connection.LocalPort instead.
Proposed API
In addition to better documentation on RequireHost, to clarify whoever is using it, I'd suggest having a RequireLocalPort extension. If I'm not mistaken, previous versions of UseHealthChecks had an optional port argument.
namespace Microsoft.AspNetCore.Builder;
public static class EndpointConventionBuilderLocalExtensions
{
public static IEndpointConventionBuilder RequireLocalPort( this IEndpointConventionBuilder builder, int port )
=> builder.AddEndpointFilter( async ( context, next ) =>
{
if ( context.HttpContext.Connection.LocalPort != port )
{
return Results.NotFound();
}
return await next( context );
} );
}Usage Examples
The code above would be replaced with
app.MapHealthChecks( "/healthz" )
.RequireLocalPort( 9001 )
.AllowAnonymous();
app.MapGet( "/", () =>
{
// ...
} )
.RequireLocalPort( 8080 );