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.
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.