gRPC & Connect

go.putnami.dev/grpc provides a gRPC server plugin and a Connect protocol gateway for serving gRPC over HTTP/1.1.

gRPC server plugin

Basic setup

import (
    "go.putnami.dev/app"
    "go.putnami.dev/grpc"
)

plugin := grpc.NewPlugin(grpc.Config{
    Port: 9090, // env: GRPC_PORT
})

// Register gRPC services
plugin.Register(func(s *grpc.Server) {
    pb.RegisterUserServiceServer(s, &userServer{})
    pb.RegisterOrderServiceServer(s, &orderServer{})
})

a := app.New("my-service")
a.Module.Use(plugin)
a.ListenAndServe()

Configuration

Field Type Default Env var Description
Port int 9090 GRPC_PORT gRPC server port

Server options

plugin := grpc.NewPlugin(grpc.Config{Port: 9090})

// Add interceptors
plugin.WithUnaryInterceptor(myInterceptor)
plugin.WithStreamInterceptor(myStreamInterceptor)

// Enable server reflection (for grpcurl, etc.)
plugin.WithReflection(true)

// Pass raw grpc.ServerOption
plugin.WithServerOption(grpc.MaxRecvMsgSize(10 << 20))

Built-in interceptors

Logging

Logs each RPC call with method, duration, and status:

import "go.putnami.dev/logger"

plugin.WithUnaryInterceptor(grpc.LoggingInterceptor(logger.Default()))

Recovery

Catches panics in handlers and returns an Internal error:

plugin.WithUnaryInterceptor(grpc.RecoveryInterceptor(logger.Default()))

DI scoping

Creates a DI scope per gRPC request, enabling per-request service resolution:

import "go.putnami.dev/inject"

plugin.WithUnaryInterceptor(grpc.DIInterceptor(containerContext))

Connect protocol gateway

The Connect gateway exposes gRPC services over HTTP/1.1 with JSON encoding, making them accessible from browsers and REST clients.

Setup

import (
    fhttp "go.putnami.dev/http"
    "go.putnami.dev/grpc"
)

server := fhttp.NewServerPlugin(fhttp.ServerConfig{Port: 3000})
gateway := grpc.NewGatewayPlugin(grpc.GatewayConfig{})

// Mount Connect handlers
gateway.MountHandler("/users.v1.UserService/", userConnectHandler)

// Register on the HTTP server
gateway.RegisterOn(server)

a := app.New("my-service")
a.Module.Use(server)
a.Module.Use(gateway)

Calling Connect endpoints

Connect endpoints are accessible as standard HTTP POST requests:

POST /users.v1.UserService/GetUser
Content-Type: application/json

{"id": "user-123"}

Response:

{"name": "Jane", "email": "jane@example.com"}

Lifecycle

Both the gRPC plugin and Connect gateway implement the standard lifecycle interfaces:

  • Configure — register services, configure interceptors
  • Start — begin listening for connections
  • Stop — graceful shutdown with drain
Application.Start()
    → gRPC.Configure()     — register services
    → gRPC.Start()      — listen on :9090
    → Gateway.Configure()  — mount handlers
    → Gateway.Start()   — ready for HTTP traffic

Application.Stop()
    → gRPC.Stop()       — graceful stop