Using aspnetcore 3.1
and the Grpc.AspNetCore
nuget package, I have managed to get gRPC services running successfully alongside standard asp.net controllers as described in this tutorial.
However I would like to bind the gRPC services to a specific port (e.g. 5001), preferably through configuration instead of code if possible. This is because I would like to limit how my gRPC services are exposed.
The closest I have come has been using RequireHost
when mapping the endpoints:
// Startup.cs
public void Configure(IApplicationBuilder app)
{
// ...
app.useEndpoints(endpoints =>
{
endpoints.MapGrpcService<MyService>()
.RequireHost("0.0.0.0:5001");
});
}
This seems to do what I want but I can't find any documentation about it, and it requires configuration in code per service. Perhaps there is a better way?
To open a gRPC connection to a service so you can send gRPC messages, you need to specify the host domain, which is the URL of the Cloud Run service or the custom domain mapped to that service, along with the port 443, which is the port expected to be used by gRPC.
Kestrel endpoints used for gRPC should be secured with TLS. In development, an endpoint secured with TLS is automatically created at https://localhost:5001 when the ASP.NET Core development certificate is present. No configuration is required. An https prefix verifies the Kestrel endpoint is using TLS.
Click on ASP.NET Core Web Application and click "Next". Enter your project name and click the "Create" button. Now, we can see that ASP.NET Core 3.0 has been listed. We Select the gRPC Service and click create to create our gRPC service application.
As far as I know, there is no other way to set a specific port for the GRPC service. The grpc service is also running on the asp.net core kestrel server, the server will listen the port not the service. If your asp.net core application just has GRPC service, you could just set the kestrel server's listen port to 5001.
ASP.NET Core gRPC has extra requirements for being used with Azure App Service or IIS. For more information on where gRPC can be used, see gRPC on .NET supported platforms. The Visual Studio Code instructions use the .NET Core CLI for ASP.NET Core development functions such as project creation.
The grpc service is also running on the asp.net core kestrel server, the server will listen the port not the service. If your asp.net core application just has GRPC service, you could just set the kestrel server's listen port to 5001.
This works (server side) with Kestrel:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5005, configure => configure.UseHttps());
});
webBuilder.UseStartup<Startup>();
});
client side:
var httpHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
using var channel = GrpcChannel.ForAddress("https://localhost:5005", new GrpcChannelOptions { HttpHandler = httpHandler } );
var client = new Greeter.GreeterClient(channel);
Note:
var httpHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
when you have a self-signed certificate without a trust chain (mostly when developing).
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
Is for support of http.
You need to configure the middleware
app.UseRouting();
app.MapWhen(context => {
return context.Connection.LocalPort == 1000
}, newApp => {
newApp.UseRouting();
newApp.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<Service1>();
}
});
app.MapWhen(context => {
return context.Connection.LocalPort == 2000
}, newApp => {
newApp.UseRouting();
newApp.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<Service2>();
}
});
As far as I know, there is no other way to set a specific port for the GRPC service.
The grpc service is also running on the asp.net core kestrel server, the server will listen the port not the service.
If your asp.net core application just has GRPC service, you could just set the kestrel server's listen port to 5001.
If you have multiple service like MVC web api or else, RequireHost is the best workaround to allow only specific port access the grpc service.
If you want to prompt the routing system for GRPC service to require the specified port, you could use below port:
routes.MapGrpcService<MyService>().RequireHost("*:5001");
In the ASP.NET Core 6.0
ports can be changed in the Properties > launchSettings.json
file. But this file is considered only if you run the server from the Visual Studio
or VS Code
.
I was trying to run the server directly using the .exe
file for testing. The server was running with the default ports: "http://localhost:5000;https://localhost:5001"
.
Finally, I changed it from the appsettings.json
for the .exe
file:
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "https://localhost:7005",
"Protocols": "Http1AndHttp2"
},
"gRPC": {
"Url": "http://localhost:5005",
"Protocols": "Http2"
}
}
You can try to use the UseWhen
method to use the MapGrpcService
endpoints only when the request uses the port you defined.
var grpcPort = 5001;
app.UseWhen(context => context.Connection.LocalPort == grpcPort,
builder =>
{
builder.UseRouting();
builder.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<MyService>();
});
});
This has the benefit of not repeating .RequireHost("*:5001");
for every single service, although repeating UseRouting
twice may induce weird behaviour: for instance, authentication may not be working unless you put in builder.UseAuthentication()
after builder.UseRouting()
.
However, this behaviour be useful if you want to have a distinct request pipeline for REST and gRPC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With