protocol

package
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: May 8, 2025 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ProtocolConnect = "connect"
	ProtocolGRPC    = "grpc"
	ProtocolGRPCWeb = "grpcweb"
)

The names of the Connect, gRPC, and gRPC-Web protocols (as exposed by Protocol). Additional protocols may be added in the future.

Variables

This section is empty.

Functions

func CheckServerStreamsCanFlush

func CheckServerStreamsCanFlush(streamType StreamType, responseWriter http.ResponseWriter) error

checkServerStreamsCanFlush ensures that bidi and server streaming handlers have received an http.ResponseWriter that implements http.Flusher, since they must flush data after sending each message.

func FlushResponseWriter

func FlushResponseWriter(w http.ResponseWriter)

func GetRegisteredProtocols

func GetRegisteredProtocols() map[string]Protocol

func IsSendUnary

func IsSendUnary(streamType StreamType) bool

IsUnary returns true if the stream type is unary or stream-server.

func IsServerStream

func IsServerStream(streamType StreamType) bool

IsServerStream returns true if the stream type is server-streaming or bidi-streaming.

func RegisterProtocol

func RegisterProtocol(p Protocol)

Types

type HandlerConnCloser

type HandlerConnCloser interface {
	StreamingHandlerConn

	Close(err error) error
}

HandlerConnCloser extends StreamingHandlerConn with a method for handlers to terminate the message exchange (and optionally send an error to the client).

func WrapHandlerConnWithCodedErrors

func WrapHandlerConnWithCodedErrors(conn HandlerConnCloser) HandlerConnCloser

WrapHandlerConnWithCodedErrors ensures that we (1) automatically code context-related errors correctly when writing them to the network, and (2) return *Errors from all exported APIs.

type IdempotencyLevel

type IdempotencyLevel int

IdempotencyLevel defines the idempotency level of an RPC method. It affects whether the request can be safely retried and what request patterns are allowed.

const (
	// IdempotencyUnknown means the idempotency level is unspecified.
	// Methods with this level may or may not be idempotent.
	IdempotencyUnknown IdempotencyLevel = 0

	// IdempotencyNoSideEffects means the method has no side effects.
	// It's semantically equivalent to "safe" methods in RFC 9110 Section 9.2.1.
	// Suitable for read-only operations like HTTP GET.
	// Requests can be safely retried.
	IdempotencyNoSideEffects IdempotencyLevel = 1

	// IdempotencyIdempotent means the method is idempotent.
	// Multiple identical requests have the same effect as a single request.
	// Equivalent to "idempotent" methods in RFC 9110 Section 9.2.2.
	// Suitable for operations like delete or update that can be safely retried.
	IdempotencyIdempotent IdempotencyLevel = 2
)

These values should match google.protobuf.MethodOptions.IdempotencyLevel.

func (IdempotencyLevel) String

func (i IdempotencyLevel) String() string

type Peer

type Peer struct {
	// Addr contains the remote address:
	// - client-side: host or host:port from server URL
	// - server-side: client IP:port
	Addr string
	// Protocol indicates the RPC protocol in use (e.g., ProtocolConnect, ProtocolGRPC).
	Protocol string
	// Query contains request query parameters (server-side only).
	Query url.Values
}

Peer describes the other party to an RPC. When accessed client-side, Addr contains the host or host:port from the server's URL. When accessed server-side, Addr contains the client's address in IP:port format.

On both the client and the server, Protocol is the RPC protocol in use. Currently, it's either ProtocolConnect, ProtocolGRPC, or ProtocolGRPCWeb, but additional protocols may be added in the future.

Query contains the query parameters for the request. For the server, this will reflect the actual query parameters sent. For the client, it is unset.

func NewPeerFromURL

func NewPeerFromURL(url *url.URL, protocol string) Peer

type Protocol

type Protocol interface {
	NewHandler(ProtocolHandlerParams) ProtocolHandler
	NewClient(ProtocolClientParams) (ProtocolClient, error)
	Name() string
}

A Protocol defines the HTTP semantics to use when sending and receiving messages. It ties together codecs, compressors, and net/http to produce Senders and Receivers.

For example, connect supports the gRPC protocol using this abstraction. Among many other things, the protocol implementation is responsible for translating timeouts from Go contexts to HTTP and vice versa. For gRPC, it converts timeouts to and from strings (for example, 10*time.Second <-> "10S"), and puts those strings into the "Grpc-Timeout" HTTP header. Other protocols might encode durations differently, put them into a different HTTP header, or ignore them entirely.

We don't have any short-term plans to export this interface; it's just here to separate the protocol-specific portions of connect from the protocol-agnostic plumbing.

func GetProtocol

func GetProtocol(name string) Protocol

type ProtocolClient

type ProtocolClient interface {
	// Peer describes the server for the RPC.
	Peer() Peer

	// WriteRequestHeader writes any protocol-specific request headers.
	WriteRequestHeader(streamType StreamType, header http.Header)

	// NewConn constructs a StreamingClientConn for the message exchange.
	//
	// Implementations should assume that the supplied HTTP headers have already
	// been populated by WriteRequestHeader. When constructing a stream for a
	// unary call, implementations may assume that the Sender's Send and Close
	// methods return before the Receiver's Receive or Close methods are called.
	NewConn(ctx context.Context, spec Spec, header http.Header) StreamingClientConn
}

Client is the client side of a protocol. HTTP clients typically use a single protocol, codec, and compressor to send requests.

type ProtocolClientParams

type ProtocolClientParams struct {
	CompressionName  string
	CompressionPools compress.ReadOnlyCompressionPools
	Codec            encoding.Codec
	CompressMinBytes int
	HTTPClient       duplex.HTTPClient
	URL              *url.URL
	BufferPool       mem.BufferPool
	ReadMaxBytes     int
	SendMaxBytes     int
	EnableGet        bool
	GetURLMaxBytes   int
	GetUseFallback   bool
	// The gRPC family of protocols always needs access to a Protobuf codec to
	// marshal and unmarshal errors.
	Protobuf encoding.Codec
}

ClientParams are the arguments provided to a Protocol's NewClient method, bundled into a struct to allow backward-compatible argument additions. Protocol implementations should take care to use the supplied Spec rather than constructing their own, since new fields may have been added.

type ProtocolHandler

type ProtocolHandler interface {
	// Methods is the set of HTTP methods the protocol can handle.
	Methods() map[string]struct{}

	// ContentTypes is the set of HTTP Content-Types that the protocol can
	// handle.
	ContentTypes() map[string]struct{}

	// SetTimeout runs before NewStream. Implementations may inspect the HTTP
	// request, parse any timeout set by the client, and return a modified
	// context and cancellation function.
	//
	// If the client didn't send a timeout, SetTimeout should return the
	// request's context, a nil cancellation function, and a nil error.
	SetTimeout(request *http.Request) (context.Context, context.CancelFunc, error)

	// CanHandlePayload returns true if the protocol can handle an HTTP request.
	// This is called after the request method is validated, so we only need to
	// be concerned with the content type/payload specifically.
	CanHandlePayload(request *http.Request, contentType string) bool

	// NewConn constructs a HandlerConn for the message exchange.
	NewConn(responseWriter http.ResponseWriter, request *http.Request) (HandlerConnCloser, bool)
}

Handler is the server side of a protocol. HTTP handlers typically support multiple protocols, codecs, and compressors.

type ProtocolHandlerParams

type ProtocolHandlerParams struct {
	Spec             Spec
	Codecs           encoding.ReadOnlyCodecs
	CompressionPools compress.ReadOnlyCompressionPools
	CompressMinBytes int
	BufferPool       mem.BufferPool
	ReadMaxBytes     int
	SendMaxBytes     int
	IdempotencyLevel IdempotencyLevel
}

HandlerParams are the arguments provided to a Protocol's NewHandler method, bundled into a struct to allow backward-compatible argument additions. Protocol implementations should take care to use the supplied Spec rather than constructing their own, since new fields may have been added.

type Spec

type Spec struct {
	StreamType       StreamType
	Schema           any    // for protobuf RPCs, a protoreflect.MethodDescriptor
	Procedure        string // for example, "/acme.foo.v1.FooService/Bar"
	IsClient         bool   // otherwise we're in a handler
	IdempotencyLevel IdempotencyLevel
}

Spec is a description of a client call or a handler invocation.

If you're using Protobuf, protoc-gen-connect-go generates a constant for the fully-qualified Procedure corresponding to each RPC in your schema.

type StreamType

type StreamType uint8

StreamType describes whether the client, server, neither, or both is streaming.

const (
	// StreamTypeUnary indicates a non-streaming RPC.
	StreamTypeUnary StreamType = 0b00
	// StreamTypeClient indicates client-side streaming.
	StreamTypeClient StreamType = 0b01
	// StreamTypeServer indicates server-side streaming.
	StreamTypeServer StreamType = 0b10
	// StreamTypeBidi indicates bidirectional streaming.
	StreamTypeBidi = StreamTypeClient | StreamTypeServer
)

func (StreamType) IsClient

func (s StreamType) IsClient() bool

func (StreamType) IsServer

func (s StreamType) IsServer() bool

func (StreamType) String

func (s StreamType) String() string

type StreamingClientConn

type StreamingClientConn interface {
	// Spec and Peer must be safe to call concurrently with all other methods.
	Spec() Spec
	Peer() Peer

	// Send, RequestHeader, and CloseRequest may race with each other, but must
	// be safe to call concurrently with all other methods.
	Send(msg any) error
	RequestHeader() http.Header
	CloseRequest() error

	// Receive, ResponseHeader, ResponseTrailer, and CloseResponse may race with
	// each other, but must be safe to call concurrently with all other methods.
	Receive(msg any) error
	ResponseHeader() http.Header
	ResponseTrailer() http.Header
	CloseResponse() error

	OnRequestSend(fn func(*http.Request))
}

StreamingClientConn is the client's view of a bidirectional message exchange. Interceptors for streaming RPCs may wrap StreamingClientConns.

StreamingClientConns write request headers to the network with the first call to Send. Any subsequent mutations are effectively no-ops. When the server is done sending data, the StreamingClientConn's Receive method returns an error wrapping io.EOF. Clients should check for this using the standard library's errors.Is. If the server encounters an error during processing, subsequent calls to the StreamingClientConn's Send method will return an error wrapping io.EOF; clients may then call Receive to unmarshal the error.

Headers and trailers beginning with "Connect-" and "Grpc-" are reserved for use by the gRPC and Connect protocols: applications may read them but shouldn't write them.

StreamingClientConn implementations provided by this module guarantee that all returned errors can be cast to [*Error] using the standard library's errors.As.

In order to support bidirectional streaming RPCs, all StreamingClientConn implementations must support limited concurrent use. See the comments on each group of methods for details.

func WrapClientConnWithCodedErrors

func WrapClientConnWithCodedErrors(conn StreamingClientConn) StreamingClientConn

WrapClientConnWithCodedErrors ensures that we always return *Errors from public APIs.

type StreamingHandlerConn

type StreamingHandlerConn interface {
	Spec() Spec
	Peer() Peer

	Receive(msg any) error
	RequestHeader() http.Header

	Send(msg any) error
	ResponseHeader() http.Header
	ResponseTrailer() http.Header
}

StreamingHandlerConn is the server's view of a bidirectional message exchange. Interceptors for streaming RPCs may wrap StreamingHandlerConns.

Like the standard library's http.ResponseWriter, StreamingHandlerConns write response headers to the network with the first call to Send. Any subsequent mutations are effectively no-ops. Handlers may mutate response trailers at any time before returning. When the client has finished sending data, Receive returns an error wrapping io.EOF. Handlers should check for this using the standard library's errors.Is.

Headers and trailers beginning with "Connect-" and "Grpc-" are reserved for use by the gRPC and Connect protocols: applications may read them but shouldn't write them.

StreamingHandlerConn implementations provided by this module guarantee that all returned errors can be cast to [*Error] using the standard library's errors.As.

StreamingHandlerConn implementations do not need to be safe for concurrent use.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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