Skip to content

Connect-RPC Server

pkg/http/connect runs a Connect-RPC server as a SyncModule. One net/http handler serves Connect, gRPC-Web, and gRPC on a single port — cleartext HTTP/2 (h2c) lets gRPC clients connect without TLS.

Register services with WithService. The registrar runs during Init (when the injector is in context) and receives the shared interceptor chain to pass into the Connect constructor.

lakta.NewRuntime(
config.NewModule(
config.WithConfigDirs(".", "./config"),
config.WithArgs(os.Args[1:]),
),
tint.NewModule(),
slog.NewModule(),
otel.NewModule(),
connect.NewModule(
connect.WithService(func(ctx context.Context, opts []connectrpc.HandlerOption) (string, http.Handler) {
return greetv1connect.NewGreetServiceHandler(NewServer(), opts...)
}),
),
)

WithService is the recommended path: it defers handler construction to Init so you can resolve dependencies with lakta.Invoke[T](ctx), and it injects the built-in interceptor chain into your handler.

For a pre-built handler that already carries its own options, use WithHandler(path, handler). Note the shared interceptor chain is not applied to handlers registered this way — the handler is mounted as-is.

The following interceptors are applied automatically (outer to inner):

  • OpenTelemetry — trace propagation (when otel is enabled)
  • Logging — structured request/response logging via slox
  • Recovery — converts panics to Connect errors
  • Errors — error normalization
  • Validation — request validation

Append your own with WithInterceptors(...); they run after the built-in chain.

By default the server listens in plaintext with h2c enabled (WithH2C), so gRPC clients connect without TLS. Configure file-path based TLS to serve HTTP/2-over-TLS instead — when TLS is set, h2c is ignored.

connect.NewModule(
connect.WithName("internal"),
connect.WithService(internalRegistrar),
),
connect.NewModule(
connect.WithName("public"),
connect.WithPort(9090),
connect.WithService(publicRegistrar),
),

Config path: modules.http.connect.<name>

hoststringdefault: 0.0.0.0

host specifies the address for the server to bind to

envLAKTA_MODULES__HTTP__CONNECT__<NAME>__HOST
portuint16default: 8080

port represents the port number on which the server listens

envLAKTA_MODULES__HTTP__CONNECT__<NAME>__PORT
h2cbooldefault: true

h2C enables cleartext HTTP/2 (h2c) so gRPC clients work without TLS. When

envLAKTA_MODULES__HTTP__CONNECT__<NAME>__H2C
read_timeouttime.Duration

readTimeout bounds reading the entire request incl. body (maps to

envLAKTA_MODULES__HTTP__CONNECT__<NAME>__READ_TIMEOUT
read_header_timeouttime.Durationdefault: 10s

readHeaderTimeout bounds reading request headers (maps to

envLAKTA_MODULES__HTTP__CONNECT__<NAME>__READ_HEADER_TIMEOUT
tlsconfig.TLS

TLS configures file-path based transport security. When unset the server

envLAKTA_MODULES__HTTP__CONNECT__<NAME>__TLS

These options can only be set in Go code via With*() functions, not via config files or environment variables.

OptionTypeDescription
WithHandler(...)map[string]http.Handlerregisters a pre-built (path, handler) pair directly; spreads a
WithService(...)[]connect.ServiceRegistraris the recommended registrar: it defers handler construction to Init
WithInterceptors(...)[]connect.Interceptorappends extra connect interceptors to the built-in chain