Reputation: 3088
I have the following exception
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2ConnectionErrorException: HTTP/2 connection error (PROTOCOL_ERROR): Invalid HTTP/2 connection preface.
I will describe my conditions. I have very simple grpc .Net Core project and I want make HTTP endpoint.
Here is Startup.cs
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddGrpc();
services.AddHttpClient<IAnalyticApiAsker, AnalyticApiAsker>();
// db context
services.AddSingleton<IApplicationMongoContext, ApplicationMongoContext>();
// repos
services.AddTransient<IWorkspacesRepo, WorkspaceRepo>();
services.AddTransient<IApplicationRepo, ApplicationRepo>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// Communication with gRPC endpoints must be made through a gRPC client.
// To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909
endpoints.MapGrpcService<ApplicationsService>();
endpoints.MapGrpcService<WorkspacesService>();
});
// I think I have to use this middleware for get http endpoints ability ?? Right?
app.UseMvc();
}
}
And Program.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
launchSettings.json
{
"profiles": {
"Dashboard": {
"commandName": "Project",
"launchBrowser": false,
"applicationUrl": "http://*:50053",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Local"
}
}
}
}
For the endpoint I have the following controller:
public class HealthController : Controller
{
[Route("/healthcheck")]
[HttpGet]
public IActionResult Index()
{
return Ok(new
{
status = "ok",
description = "works"
});
}
}
But when I request from a browser my application's URL http://localhost:50053/healthcheck
I have this exception. it looks like Kestrel configured only for http2. If it's true, how to switch on HTTP handling?
Ok, after some researching I have understood the following. It's impossible to switch on both protocol types handling: grpc (that works with HTTP 2) and ordinary http1 at the same time. Am I right?
I have modified my Startapp.cs
to:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureKestrel(options =>
{
options.ListenLocalhost(50053, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});
})
.UseStartup<Startup>();
HttpProtocols.Http1AndHttp2
this property has variant for each HTTP type (Http1, Http, Http1AndHttp2). But it does not work for GRPC. I think it's happening because of whether to use http1 to GRPC or http2. And I don't know how to set up it.
So, listenOptions.Protocols = HttpProtocols.Http1
- works for web,
listenOptions.Protocols = HttpProtocols.Http2
- works for GRPC and
listenOptions.Protocols = HttpProtocols.Http1AndHttp2
- works for web.
I'm not sure if it answers or not, but I have solved the task with the help of the following Program.cs
modification:
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureKestrel(options =>
{
options.ListenLocalhost(80, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1;
});
options.ListenLocalhost(50053, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
})
.UseStartup<Startup>();
}
Now I can work with http1 and http2. But now I have a new problem, it works only on localhost.
Upvotes: 11
Views: 9101
Reputation: 21
grpc need tls.
TLS is used for more than securing communication. The TLS Application-Layer Protocol Negotiation (ALPN) handshake is used to negotiate the connection protocol between the client and the server when an endpoint supports multiple protocols. This negotiation determines whether the connection uses HTTP/1.1 or HTTP/2.
https://learn.microsoft.com/en-us/aspnet/core/grpc/aspnetcore?view=aspnetcore-3.1&tabs=visual-studio
Upvotes: 1
Reputation: 3088
Ok, I have solved it with the help of the following Program.cs
modification:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureKestrel(options =>
{
options.ListenAnyIP(80, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1;
});
options.ListenAnyIP(50053, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
})
.UseStartup<Startup>();
}
Now I can work with GRPC and http1 in the same time, and connection allowed for any IP.
I hope it will useful for somebody who will add http1 to GRPC configured project.
Upvotes: 8