package
0.0.0-20250914193024-d72055214c86
Repository: https://github.com/bryk-io/pkg.git
Documentation: pkg.go.dev

# Packages

No description provided by the author
No description provided by the author

# README

Package drpc

DRPC is a lightweight, drop-in, protocol buffer-based gRPC replacement. The DRPC protocol strips out huge swaths of unnecessary complexity; it is implemented in just a few thousand lines of straightforward Go! DRPC is small, extensible, efficient, and can still be autogenerated from your existing Protobuf definition files.

More information: https://github.com/storj/drpc

Server

This package simplifies the process of running a DRPC server in production by providing often required additional functionality, for example:

  • Properly setup TLS to provide secure communication channels
  • Protect against panics produced by external services
  • Generate structured logs for all processed requests
  • Request authentication/authorization (authN, authZ)
  • Rate limiting requests to avoid resource exhaustion attacks

For example, to start a typical production server.

// Token validation function. This will usually handle JWT or PASETO
// tokens for example.
myCustomCredsValidation := func(token string) bool {
  return token == "super-secure-credentials"
}

// Server TLS settings. Cert, key and CA are usually read from a file
// or another secret-management tool.
tlsSettings := ServerTLS{
  Cert:             my-cert-pem,
  PrivateKey:       my-key-pem,
  CustomCAs:        [][]byte{my-ca-cert-pem},
  IncludeSystemCAs: true,
}

// Define the middleware elements to use.
// In this case:
// - Use zerolog to produce "pretty" detailed output
// - Limit the processing to 100 RPC requests per-second
// - Provide a custom token-based authentication mechanism
// - Prevent the server from crashing on `panic` calls
smw := []srvmw.Middleware{
  srvmw.Logging(xlog.WithZero(true, "error").Sub(xlog.Fields{"component": "server"}), nil),
  srvmw.RateLimit(100),
  srvmw.AuthByToken("auth.token", myCustomCredsValidation),
  srvmw.PanicRecovery(),
}

// RPC server settings.
// - The server will listen on TCP port 8080
// - The server will handle DRPC and HTTP requests
// - The server will use TLS for secure connections
// - The server will provide bi-directional streaming over WebSockets (and DRPC)
opts := []Option{
  WithServiceProvider(myServiceImplementation()),
  WithPort(8080),
  WithHTTP(),
  WithMiddleware(smw...),
  WithTLS(tlsSettings),
  WithWebSocketProxy(
    ws.EnableCompression(),
    ws.CheckOrigin(func(r *http.Request) bool { return true }),
    ws.HandshakeTimeout(2*time.Second),
    ws.SubProtocols([]string{"rfb", "sip"}),
  ),
}

// Create and start the new server
srv, err := NewServer(opts...)
if err != nil {
  panic(err)
}
srv.Start()

Client

This package simplifies the process of running a DRPC client in production by providing often required additional functionality, for example:

  • Concurrent RPC requests (using connection pools)
  • Properly setup TLS to provide secure communication channels
  • Protect against panics produced by external services
  • Generate structured logs for all processed requests
  • Provide custom metadata on all requests send to the server (e.g. credentials)

For example, to start a typical production client.

// Custom metadata. Can be used to provide identifiers, credentials or
// additional contextual details.
kv := map[string]string{
  "metadata.user": "rick",
}

// Client TLS settings.
tlsSettings := ClientTLS{
  IncludeSystemCAs: true,
  CustomCAs:        [][]byte{ca-cert-pem},
  ServerName:       "my-server.local.acme.com",
}

// Client middleware.
// - Provide custom details (`kv`) on every request
// - Use zerolog to produce "pretty" detailed output
// - Limit the client to 100 RPC requests per-second
// - Prevent the client from crashing on `panic` calls
cmw := []clmw.Middleware{
  clmw.Metadata(kv),
  clmw.Logging(xlog.WithZero(true, "error").Sub(xlog.Fields{"component": "client"}), nil),
  clmw.RateLimit(100),
  clmw.PanicRecovery(),
}

// Client options.
// - Up to 5 concurrent RPC calls
// - Include a protocol selection header (between DRPC and HTTP)
// - Use TLS to verify server's identity and establish secure connections
opts := []ClientOption{
  WithProtocolHeader(),
  WithPoolCapacity(5),
  WithClientTLS(tlsSettings),
  WithClientMiddleware(cmw...),
}

// Start new client
cl, err := NewClient("tcp", ":8080", opts...)
if err != nil {
  panic(err)
}

// When no longer needed, the client must be closed
defer cl.Close()

// The client can be used directly to create stubs to consume
// specific DRPC services.
// RPC request
mySvc := samplev1.NewDRPCFooAPIClient(cl)
res, _ := mySvc.Ping(context.Background(), &emptypb.Empty{})

Custom Middleware

You can provide your own custom middleware to extend/adjust the processing of RPC requests on both server and client using the decorator pattern. You can then use the WithMiddleware and WithClientMiddleware options when creating a new server or client instance.