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 ¶
func NewForwarder(ka *keepalive.ClientParameters, creds credentials.TransportCredentials, dialOpts []grpc.DialOption) *Forwarder
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) ParseAs ¶
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.
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) 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 (*Server) GetGRPCServer ¶
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) 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)