'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
*Predicatemethods? - 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 |
|---|
