proxy

package
v0.0.0-...-a6e4b1f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 23, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package proxy implements a transparent gRPC proxy with plugin support

Package proxy implements a transparent gRPC proxy with plugin support

Package proxy implements transparent gRPC message forwarding. It forwards raw gRPC frames without deserializing protobuf messages.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	DefaultBackend string
	// KeepaliveParams, if set, controls client-side keepalive for backend
	// connections. Leave nil to use gRPC defaults — setting an aggressive
	// Time (e.g. 10s) can violate a backend's EnforcementPolicy.MinTime
	// (vtctld defaults to 5m) and trigger GOAWAY ENHANCE_YOUR_CALM.
	KeepaliveParams *keepalive.ClientParameters
	// BackendTransportCreds sets the transport credentials for backend
	// connections. When nil, insecure credentials are used.
	BackendTransportCreds credentials.TransportCredentials
	// BackendDialOptions supplies additional grpc.DialOption values
	// (stream interceptors, stats handlers, etc.) for backend connections.
	// These are appended after credentials and keepalive options.
	// Note: unary interceptors have no effect because all RPCs are
	// proxied as bidirectional streams via grpc.NewClientStream.
	BackendDialOptions []grpc.DialOption
	// Hooks supplies optional callbacks for proxy lifecycle events. Leave
	// nil to disable all hooks.
	Hooks *Hooks
}

type ConnectionCache

type ConnectionCache struct {
	// contains filtered or unexported fields
}

ConnectionCache maintains a pool of reusable gRPC connections to backend servers. It's safe for concurrent use by multiple goroutines.

func NewConnectionCache

func NewConnectionCache(ka *keepalive.ClientParameters, creds credentials.TransportCredentials, dialOpts []grpc.DialOption) *ConnectionCache

NewConnectionCache creates an empty connection cache. If ka is nil, no client keepalive parameters are applied (gRPC defaults). If creds is nil, insecure credentials are used. dialOpts are appended after credentials and keepalive (interceptors, stats handlers, etc.).

func (*ConnectionCache) Close

func (c *ConnectionCache) Close()

Close closes all cached connections and clears the cache. Should be called when shutting down the proxy server.

func (*ConnectionCache) Get

func (c *ConnectionCache) Get(backend string) (*grpc.ClientConn, error)

Get retrieves or creates a connection to the backend server. Uses double-check locking for thread-safe lazy initialization.

func (*ConnectionCache) Remove

func (c *ConnectionCache) Remove(backend string)

Remove closes and removes a specific backend connection from the cache. Useful when a backend server is no longer available.

type Forwarder

type Forwarder struct {
	// contains filtered or unexported fields
}

Forwarder handles bidirectional gRPC stream proxying between client and backend server. It maintains a connection cache to reuse backend connections.

func NewForwarder

NewForwarder creates a new Forwarder with an empty connection cache. ka is optional keepalive; creds overrides default insecure transport credentials (nil = insecure); dialOpts are additional backend dial options.

func (*Forwarder) Close

func (f *Forwarder) Close()

Close releases all cached backend connections. Should be called when shutting down the proxy server.

func (*Forwarder) Forward

func (f *Forwarder) Forward(
	ctx context.Context,
	fullMethodName string,
	serverStream grpc.ServerStream,
	backend string,
	additionalMD metadata.MD,
	firstFrame *Frame,
) error

Forward proxies a gRPC stream between client and backend server.

It creates two goroutines for bidirectional forwarding:

  • c2s (client to backend): serverStream -> clientStream
  • s2c (backend to client): clientStream -> serverStream

Parameters:

  • ctx: request context
  • fullMethodName: gRPC method name (e.g., "/service.Service/Method")
  • serverStream: incoming stream from client
  • backend: backend server address (e.g., "localhost:50051")
  • additionalMD: extra metadata to send to backend (can be set by middlewares)
  • firstFrame: first message frame already read from client (can be nil)

Returns an error if proxying fails, or nil on successful completion.

type Frame

type Frame struct {
	// contains filtered or unexported fields
}

Frame represents a raw gRPC message frame containing unparsed bytes. It's used as the message type for the ProxyCodec to enable transparent forwarding.

func (*Frame) Data

func (f *Frame) Data() []byte

Data returns the raw frame bytes.

func (*Frame) ParseAs

func (f *Frame) ParseAs(msg proto.Message) error

ParseAs parses the frame data into a specific protobuf message type. This is useful when middlewares need to inspect the actual message content.

func (*Frame) ProtoMessage

func (f *Frame) ProtoMessage()

ProtoMessage is a marker method to satisfy the proto.Message interface.

func (*Frame) Reset

func (f *Frame) Reset()

Reset clears the frame data.

func (*Frame) String

func (f *Frame) String() string

String returns a human-readable representation of the frame.

type Hooks

type Hooks struct {
	// OnFirstFrameError is called when the first message frame from the
	// client cannot be parsed as a gRPC message. Returning a non-nil
	// error aborts the request with that error (sent to the client);
	// returning nil lets the request proceed into the middleware chain
	// with RequestInfo.FirstPayload set to nil.
	OnFirstFrameError func(req *middleware.RequestInfo, err error) error
}

Hooks groups optional callbacks the proxy invokes at well-defined points. All fields are optional; a nil field means "no callback".

type ProxyCodec

type ProxyCodec struct{}

ProxyCodec is a custom codec for transparent gRPC message proxying.

Unlike standard gRPC codecs (like protobuf), ProxyCodec:

  • Does NOT deserialize messages
  • Does NOT serialize messages
  • Simply wraps/unwraps raw bytes in Frame objects

This enables transparent forwarding: bytes received from client are directly forwarded to backend without any protobuf parsing overhead.

func (*ProxyCodec) Marshal

func (c *ProxyCodec) Marshal(v any) ([]byte, error)

Marshal extracts raw bytes from a Frame. Called by gRPC when sending messages.

func (*ProxyCodec) Name

func (c *ProxyCodec) Name() string

Name returns the codec name.

func (*ProxyCodec) String

func (c *ProxyCodec) String() string

String returns the codec description.

func (*ProxyCodec) Unmarshal

func (c *ProxyCodec) Unmarshal(data []byte, v any) error

Unmarshal wraps raw bytes into a Frame. Called by gRPC when receiving messages.

IMPORTANT: This directly references the input data slice. The data slice is owned by gRPC and will be reused after RecvMsg returns, so callers must NOT retain references to frame.data beyond RecvMsg.

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(config *Config) (*Server, error)

func (*Server) GetGRPCServer

func (s *Server) GetGRPCServer() *grpc.Server

GetGRPCServer exposes the underlying *grpc.Server so library users can register additional services (health, reflection, their own handlers) alongside the proxy on the same listener.

func (*Server) Start

func (s *Server) Start(ctx context.Context, addr string) error

func (*Server) Stop

func (s *Server) Stop()

func (*Server) TransparentHandler

func (s *Server) TransparentHandler() grpc.StreamHandler

TransparentHandler creates a grpc.StreamHandler that proxies all requests. This is registered as grpc.UnknownServiceHandler to handle any unregistered service.

func (*Server) Use

func (s *Server) Use(mw middleware.Middleware)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL