Skip to content

Configuration Kestrel HTTP 2

quyvu edited this page Oct 13, 2026 · 2 revisions

Kestrel (HTTP/2)

Configure Kestrel so a service can serve its REST endpoints and the FxMap gRPC transport side by side.

Why Two Endpoints?

The FxMap.Grpc transport needs an HTTP/2 endpoint on the service that owns the data. Without TLS, browsers, health checks and most HTTP tooling still speak HTTP/1.1, and Kestrel cannot negotiate HTTP/2 over plain HTTP on a shared port. The usual answer is one endpoint per protocol:

Http1 (port 8080)

REST controllers, minimal APIs, Swagger, health checks and metrics.

Http2 (port 8081)

The FxMap gRPC endpoint that other services call through AddGrpcHosts.

Configure It in appsettings.json

Kestrel reads the Kestrel section of your configuration automatically, so no extra code is needed:

{
  "Kestrel": {
    "Endpoints": {
      "Http1": {
        "Url": "http://*:8080",
        "Protocols": "Http1"
      },
      "Http2": {
        "Url": "http://*:8081",
        "Protocols": "Http2"
      }
    }
  }
}
Setting Meaning
Http1, Http2 Endpoint names. They are labels only; pick any names you like.
Url Address to listen on. * binds every network interface, which is what you want inside a container.
Protocols Http1, Http2 or Http1AndHttp2.

Wire Up the Server and the Client

The service that owns the data exposes the FxMap gRPC endpoint. Nothing in the code refers to the ports; they come from the configuration above.

Server (the service that owns the data)

builder.Services.AddGrpc();
builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
})
.AddEntityFrameworkCore(o => o.AddDbContexts(typeof(AppDbContext)));
 
var app = builder.Build();
app.MapFxMapperGrpc();
app.Run();

Client (the service that needs the data)

Point the client at the HTTP/2 port, not the REST port:

builder.Services.AddFxMap(cfg =>
{
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
    cfg.AddGrpcClients(c => c.AddGrpcHosts("http://user-service:8081"));
});

Configure It in Code Instead

If you prefer code over configuration files, the same two endpoints look like this:

using Microsoft.AspNetCore.Server.Kestrel.Core;
 
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(8080, listen => listen.Protocols = HttpProtocols.Http1);
    options.ListenAnyIP(8081, listen => listen.Protocols = HttpProtocols.Http2);
});

Use one approach per port. When Kestrel:Endpoints is configured, Kestrel ignores ASPNETCORE_URLS and --urls.

One Endpoint with TLS

With TLS, a single endpoint can serve both protocols because HTTP/2 is negotiated during the handshake. This is the simplest setup when you terminate TLS in the service itself:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://*:8443",
        "Protocols": "Http1AndHttp2"
      }
    }
  }
}

Clients then use AddGrpcHosts("https://user-service:8443"). Without TLS, Http1AndHttp2 falls back to HTTP/1.1 and gRPC calls fail, so use the two-endpoint layout above instead.

Docker and Kubernetes

Expose both ports and point health checks at the HTTP/1.1 one. Endpoints can also be set through environment variables, which is handy in container manifests:

# docker-compose.yml
services:
  user-service:
    image: my-company/user-service
    ports:
      - "8080:8080"   # REST / health
      - "8081:8081"   # FxMap gRPC
    environment:
      Kestrel__Endpoints__Http1__Url: http://*:8080
      Kestrel__Endpoints__Http1__Protocols: Http1
      Kestrel__Endpoints__Http2__Url: http://*:8081
      Kestrel__Endpoints__Http2__Protocols: Http2

Troubleshooting

  • Client reports a protocol or connection error: it is calling the HTTP/1.1 port. Use the Http2 port in AddGrpcHosts.
  • gRPC works locally but not in a container: check that the Http2 port is published and that the URL uses * or 0.0.0.0, not localhost.
  • Health checks fail: probe the Http1 port; many probes cannot speak HTTP/2 without TLS.
  • Message-based transports (NATS, RabbitMQ, Kafka, Azure Service Bus, SQS) do not need any of this.

Source: https://fxmapper.net/docs/configuration/kestrel/ — the website is always the most up to date version.

Clone this wiki locally