'Filtering connections on my ASP.NET Core sever between Razor/MVC and gRPC, depending on Kestrel endpoint

In my .NET 6 ASP application I plan on exposing 3 types of network endpoints:

  • Razor pages-based web UI, listening either on a TCP port or Unix socket
  • Public gRPC API, listening on TCP or Unix socket as well
  • Server management gRPC API for internal use only, listening only on a Unix socket for security reasons

The public parts (Razor and public gRPC) could be used behind a reverse proxy, which is why I plan on allowing both TCP and Unix sockets (in case the proxy is on the same machine, but I can make them TCP-only). I also need to have them all in the same Host, so they can access the same services (same instances, not just services configured in similar ways), and so I can also register regular Hosted Services. Lastly, since both Microsoft and gRPC documentation say to not use Grpc.Core, I do not wish to use it, even though it would completely solve my problem.

Since it is not possible to have several WebHosts inside a single Generic Host, my best bet is now to rely on MapWhen to direct the requests depending on which endpoint received the connection. However, the only data I have for the MapWhen predicate idicates the connection origin using the IPAddress class (via HttpContext.Connection), which cannot represent a Unix socket, so I can't use it to reliably identify the connection source.

If I go the MapWhen route, the code would have the following structure:

public void KestrelSetupCallback(KestrelServerOptions options) {
    // The two *Endpoint below are either IPEndpoint or UnixSocketEndpoint
    // obtained from app configuration
    options.Listen(razorEndpoint, o => o.Protocols = HttpProtocols.Http1AndHttp2);
    options.Listen(apiEndpoint, o => o.Protocols = HttpProtocols.Http2);
    options.ListenUnixSocket(managementSocketPath, o => o.Protocols = HttpProtocols.Http2);
}

public void WebappSetupCallback(IApplicationBuilder app) {
    // Additional middlewares can be added here if needed by the predicates
    app.MapWhen(RazorPredicate, RazorSetupCallback);
    app.MapWhen(ApiPredicate, ApiSetupCallback);
    app.MapWhen(ManagementPredicate, ManagementSetupCallback);
}

I have found about the ListenOptions.Use method , which I could call on each endpoint's ListenOptions to add a connection middleware that would set a Feature identifying the endpoint. I am not sure if that is possible though (if the IFeatureCollection is writable at this point), and I would like to know if there are other options.

  • Would this approach work, given my use case? Would I need to alter the code structure?
  • Aside from that, what approach could I take to implement the *Predicate methods?
  • Is there a better alternate method to achieve my use case? This feels very XYZ Problem to me and I'm afraid of missing a feature designed precisely for that.


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source