Documentation
¶
Overview ¶
Package triple is a slim RPC framework built on Protocol Buffers and net/http. In addition to supporting its own protocol, Triple handlers and clients are wire-compatible with gRPC, including streaming.
This documentation is intended to explain each type and function in isolation. Walkthroughs, FAQs, and other narrative docs are available on the dubbo-go website, and there's a working demonstration service on Github.
Example (Client) ¶
logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */) // Unfortunately, pkg.go.dev can't run examples that actually use the // network. To keep this example runnable, we'll use an HTTP server and // client that communicate over in-memory pipes. The client is still a plain // *http.Client! httpClient := examplePingServer.Client() // By default, clients use the GRPC protocol. Add triple_protocol.WithTriple() or // triple_protocol.WithGRPCWeb() to switch protocols. client := pingv1connect.NewPingServiceClient( httpClient, examplePingServer.URL(), ) response := tri.NewResponse(&pingv1.PingResponse{}) if err := client.Ping( context.Background(), tri.NewRequest(&pingv1.PingRequest{Number: 42}), response, ); err != nil { logger.Println("error:", err) return } logger.Println("response content-type:", response.Header().Get("Content-Type")) logger.Println("response message:", response.Msg)
Output: response content-type: application/grpc+proto response message: number:42
Example (Handler) ¶
package main import ( "context" "net/http" ) import ( triple "gitee.com/git4chen/dubbo-go/protocol/triple/triple_protocol" pingv1 "gitee.com/git4chen/dubbo-go/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1" "gitee.com/git4chen/dubbo-go/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect" ) // ExamplePingServer implements some trivial business logic. The Protobuf // definition for this API is in proto/triple/ping/v1/ping.proto. type ExamplePingServer struct { pingv1connect.UnimplementedPingServiceHandler } // Ping implements pingv1connect.PingServiceHandler. func (*ExamplePingServer) Ping( _ context.Context, request *triple.Request, ) (*triple.Response, error) { msg := request.Msg.(*pingv1.PingRequest) return triple.NewResponse(&pingv1.PingResponse{ Number: msg.Number, Text: msg.Text, }), nil } func main() { // protoc-gen-triple-go generates constructors that return plain net/http // Handlers, so they're compatible with most Go HTTP routers and middleware // (for example, net/http's StripPrefix). Each handler automatically supports // the Connect, gRPC, and gRPC-Web protocols. mux := http.NewServeMux() mux.Handle( pingv1connect.NewPingServiceHandler( &ExamplePingServer{}, // our business logic ), ) // You can serve gRPC's health and server reflection APIs using // github.com/bufbuild/triple-grpchealth-go and // github.com/bufbuild/triple-grpcreflect-go. _ = http.ListenAndServeTLS( "localhost:8080", "internal/testdata/server.crt", "internal/testdata/server.key", mux, ) // To serve HTTP/2 requests without TLS (as many gRPC clients expect), import // golang.org/x/net/http2/h2c and golang.org/x/net/http2 and change to: // _ = http.ListenAndServe( // "localhost:8080", // h2c.NewHandler(mux, &http2.Server{}), // ) }
Output:
Index ¶
- Constants
- func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context
- func DecodeBinaryHeader(data string) ([]byte, error)
- func EncodeBinaryHeader(data []byte) string
- func ExtractFromOutgoingContext(ctx context.Context) http.Header
- func FromIncomingContext(ctx context.Context) (http.Header, bool)
- func IsEnded(err error) bool
- func IsWireError(err error) bool
- func MaxBytesHandler(h http.Handler, n int64) http.Handler
- func NewOutgoingContext(ctx context.Context, data http.Header) context.Context
- func SendHeader(ctx context.Context, header http.Header) error
- func SetHeader(ctx context.Context, header http.Header) error
- func SetTrailer(ctx context.Context, trailer http.Header) error
- type AnyRequest
- type AnyResponse
- type BidiStream
- func (b *BidiStream) Conn() StreamingHandlerConn
- func (b *BidiStream) ExportableHeader() http.Header
- func (b *BidiStream) Peer() Peer
- func (b *BidiStream) Receive(msg interface{}) error
- func (b *BidiStream) RequestHeader() http.Header
- func (b *BidiStream) ResponseHeader() http.Header
- func (b *BidiStream) ResponseTrailer() http.Header
- func (b *BidiStream) Send(msg interface{}) error
- func (b *BidiStream) Spec() Spec
- type BidiStreamForClient
- func (b *BidiStreamForClient) CloseRequest() error
- func (b *BidiStreamForClient) CloseResponse() error
- func (b *BidiStreamForClient) Conn() (StreamingClientConn, error)
- func (b *BidiStreamForClient) Peer() Peer
- func (b *BidiStreamForClient) Receive(msg interface{}) error
- func (b *BidiStreamForClient) RequestHeader() http.Header
- func (b *BidiStreamForClient) ResponseHeader() http.Header
- func (b *BidiStreamForClient) ResponseTrailer() http.Header
- func (b *BidiStreamForClient) Send(msg interface{}) error
- func (b *BidiStreamForClient) Spec() Spec
- type Client
- func (c *Client) CallBidiStream(ctx context.Context) (*BidiStreamForClient, error)
- func (c *Client) CallClientStream(ctx context.Context) (*ClientStreamForClient, error)
- func (c *Client) CallServerStream(ctx context.Context, request *Request) (*ServerStreamForClient, error)
- func (c *Client) CallUnary(ctx context.Context, request *Request, response *Response) error
- type ClientOption
- func WithAcceptCompression(name string, newDecompressor func() Decompressor, ...) ClientOption
- func WithClientOptions(options ...ClientOption) ClientOption
- func WithHessian2() ClientOption
- func WithMsgPack() ClientOption
- func WithProtoJSON() ClientOption
- func WithSendCompression(name string) ClientOption
- func WithSendGzip() ClientOption
- func WithTimeout(timeout time.Duration) ClientOption
- func WithTriple() ClientOption
- type ClientStream
- func (c *ClientStream) Conn() StreamingHandlerConn
- func (c *ClientStream) Err() error
- func (c *ClientStream) Msg() interface{}
- func (c *ClientStream) Peer() Peer
- func (c *ClientStream) Receive(msg interface{}) bool
- func (c *ClientStream) RequestHeader() http.Header
- func (c *ClientStream) Spec() Spec
- type ClientStreamForClient
- func (c *ClientStreamForClient) CloseAndReceive(response *Response) error
- func (c *ClientStreamForClient) Conn() (StreamingClientConn, error)
- func (c *ClientStreamForClient) Peer() Peer
- func (c *ClientStreamForClient) RequestHeader() http.Header
- func (c *ClientStreamForClient) Send(request interface{}) error
- func (c *ClientStreamForClient) Spec() Spec
- type Code
- type Codec
- type Compressor
- type Decompressor
- type Error
- type ErrorDetail
- type ErrorWriter
- type ExpectedCodecNameOption
- type HTTPClient
- type Handler
- func NewBidiStreamHandler(procedure string, streamFunc func(context.Context, *BidiStream) error, ...) *Handler
- func NewClientStreamHandler(procedure string, ...) *Handler
- func NewCompatStreamHandler(procedure string, srv interface{}, typ StreamType, ...) *Handler
- func NewCompatUnaryHandler(procedure string, method string, srv interface{}, unary MethodHandler, ...) *Handler
- func NewServerStreamHandler(procedure string, reqInitFunc func() interface{}, ...) *Handler
- func NewUnaryHandler(procedure string, reqInitFunc func() interface{}, ...) *Handler
- type HandlerOption
- func WithCompression(name string, newDecompressor func() Decompressor, ...) HandlerOption
- func WithHandlerOptions(options ...HandlerOption) HandlerOption
- func WithRecover(handle func(context.Context, Spec, http.Header, interface{}) error) HandlerOption
- func WithRequireTripleProtocolHeader() HandlerOption
- type IdempotencyLevel
- type Interceptor
- type MethodHandler
- type Option
- func WithCodec(codec Codec) Option
- func WithCompressMinBytes(min int) Option
- func WithExpectedCodecName(ExpectedCodecName string) Option
- func WithGroup(group string) Option
- func WithIdempotency(idempotencyLevel IdempotencyLevel) Option
- func WithInterceptors(interceptors ...Interceptor) Option
- func WithOptions(options ...Option) Option
- func WithReadMaxBytes(max int) Option
- func WithSendMaxBytes(max int) Option
- func WithVersion(version string) Option
- type Peer
- type Request
- type Response
- type Server
- func (s *Server) GracefulStop(ctx context.Context) error
- func (s *Server) RegisterBidiStreamHandler(procedure string, stream func(context.Context, *BidiStream) error, ...) error
- func (s *Server) RegisterClientStreamHandler(procedure string, ...) error
- func (s *Server) RegisterCompatStreamHandler(procedure string, srv interface{}, typ StreamType, ...) error
- func (s *Server) RegisterCompatUnaryHandler(procedure string, method string, srv interface{}, unary MethodHandler, ...) error
- func (s *Server) RegisterServerStreamHandler(procedure string, reqInitFunc func() interface{}, ...) error
- func (s *Server) RegisterUnaryHandler(procedure string, reqInitFunc func() interface{}, ...) error
- func (s *Server) Run() error
- func (s *Server) Stop() error
- type ServerStream
- type ServerStreamForClient
- func (s *ServerStreamForClient) Close() error
- func (s *ServerStreamForClient) Conn() (StreamingClientConn, error)
- func (s *ServerStreamForClient) Err() error
- func (s *ServerStreamForClient) Msg() interface{}
- func (s *ServerStreamForClient) Receive(msg interface{}) bool
- func (s *ServerStreamForClient) ResponseHeader() http.Header
- func (s *ServerStreamForClient) ResponseTrailer() http.Header
- type Spec
- type StreamType
- type StreamingClientConn
- type StreamingClientFunc
- type StreamingHandlerConn
- type StreamingHandlerFunc
- type UnaryFunc
- type UnaryHandlerFunc
- type UnaryInterceptorFunc
- func (f UnaryInterceptorFunc) WrapStreamingClient(next StreamingClientFunc) StreamingClientFunc
- func (f UnaryInterceptorFunc) WrapStreamingHandler(next StreamingHandlerFunc) StreamingHandlerFunc
- func (f UnaryInterceptorFunc) WrapUnary(next UnaryFunc) UnaryFunc
- func (f UnaryInterceptorFunc) WrapUnaryHandler(next UnaryHandlerFunc) UnaryHandlerFunc
Examples ¶
Constants ¶
const ( TripleContentType = "application/grpc+proto" TripleUserAgent = "grpc-go/1.35.0-dev" TripleServiceVersion = "tri-service-version" TripleAttachement = "tri-attachment" TripleServiceGroup = "tri-service-group" TripleRequestID = "tri-req-id" TripleTraceID = "tri-trace-traceid" TripleTraceRPCID = "tri-trace-rpcid" TripleTraceProtoBin = "tri-trace-proto-bin" TripleUnitInfo = "tri-unit-info" )
These keys are for compatible usage
const ( ProtocolTriple = "triple" ProtocolGRPC = "grpc" ProtocolGRPCWeb = "grpcweb" )
The names of the Triple, gRPC, and gRPC-Web protocols (as exposed by [Peer.Protocol]). Additional protocols may be added in the future.
const ( IsAtLeastVersion0_0_1 = true IsAtLeastVersion0_1_0 = true IsAtLeastVersion1_6_0 = true )
These constants are used in compile-time handshakes with triple's generated code.
const Version = "0.1.0"
Version is the semantic version of the triple module.
Variables ¶
This section is empty.
Functions ¶
func AppendToOutgoingContext ¶
AppendToOutgoingContext merges kv pairs from user and existing headers. It is used for passing headers to server-side. It is like grpc.AppendToOutgoingContext. Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
func DecodeBinaryHeader ¶
DecodeBinaryHeader base64-decodes the data. It can decode padded or unpadded values. Following usual HTTP semantics, multiple base64-encoded values may be joined with a comma. When receiving such comma-separated values, split them with strings.Split before calling DecodeBinaryHeader.
Binary headers sent using the Triple, gRPC, and gRPC-Web protocols have keys ending in "-Bin".
func EncodeBinaryHeader ¶
EncodeBinaryHeader base64-encodes the data. It always emits unpadded values.
In the Triple, gRPC, and gRPC-Web protocols, binary headers must have keys ending in "-Bin".
func FromIncomingContext ¶
FromIncomingContext retrieves headers passed by client-side. It is like grpc.FromIncomingContext. it must call after append/setOutgoingContext to return current value Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#receiving-metadata-1.
func IsEnded ¶
IsEnded is a convenient function indicating the end of stream. It is introduced to not expose io.EOF to beginners. Please refer to https://github.com/apache/dubbo-go/pull/2416#discussion_r1318558801
func IsWireError ¶
IsWireError checks whether the error was returned by the server, as opposed to being synthesized by the client.
Clients may find this useful when deciding how to propagate errors. For example, an RPC-to-HTTP proxy might expose a server-sent CodeUnknown as an HTTP 500 but a client-synthesized CodeUnknown as a 503.
func MaxBytesHandler ¶
MaxBytesHandler is the same as http.MaxBytesHandler for compatibility since there is another MaxBytesHandler in maxbytes_low_version.go.
func NewOutgoingContext ¶
NewOutgoingContext sets headers entirely. If there are existing headers, they would be replaced. It is used for passing headers to server-side. It is like grpc.NewOutgoingContext. Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
func SendHeader ¶
SendHeader is used for setting response headers in server-side and send them directly. It is like grpc.SendHeader(ctx, header). Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#unary-call-2.
func SetHeader ¶
SetHeader is used for setting response header in server-side. It is like grpc.SendHeader(ctx, header) but not send header. Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#unary-call-2.
func SetTrailer ¶
SetTrailer is used for setting response trailers in server-side. It is like grpc.SetTrailer(ctx, header). Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#unary-call-2.
Types ¶
type AnyRequest ¶
type AnyRequest interface { Any() interface{} Spec() Spec Peer() Peer Header() http.Header // contains filtered or unexported methods }
AnyRequest is the common method set of every Request, regardless of type parameter. It's used in unary interceptors.
Headers and trailers beginning with "Triple-" and "Grpc-" are reserved for use by the gRPC and Triple protocols: applications may read them but shouldn't write them.
To preserve our ability to add methods to this interface without breaking backward compatibility, only types defined in this package can implement AnyRequest.
type AnyResponse ¶
type AnyResponse interface { Any() interface{} Header() http.Header Trailer() http.Header // contains filtered or unexported methods }
AnyResponse is the common method set of every Response, regardless of type parameter. It's used in unary interceptors.
Headers and trailers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and Grpc protocols: applications may read them but shouldn't write them.
To preserve our ability to add methods to this interface without breaking backward compatibility, only types defined in this package can implement AnyResponse.
type BidiStream ¶
type BidiStream struct {
// contains filtered or unexported fields
}
BidiStream is the handler's view of a bidirectional streaming RPC.
It's constructed as part of Handler invocation, but doesn't currently have an exported constructor.
func (*BidiStream) Conn ¶
func (b *BidiStream) Conn() StreamingHandlerConn
Conn exposes the underlying StreamingHandlerConn. This may be useful if you'd prefer to wrap the connection in a different high-level API.
func (*BidiStream) ExportableHeader ¶
func (b *BidiStream) ExportableHeader() http.Header
ExportableHeader returns the headers could be exported to users.
func (*BidiStream) Receive ¶
func (b *BidiStream) Receive(msg interface{}) error
Receive a message. When the client is done sending messages, Receive will return an error that wraps io.EOF.
func (*BidiStream) RequestHeader ¶
func (b *BidiStream) RequestHeader() http.Header
RequestHeader returns the headers received from the client.
func (*BidiStream) ResponseHeader ¶
func (b *BidiStream) ResponseHeader() http.Header
ResponseHeader returns the response headers. Headers are sent with the first call to Send.
Headers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols. Applications shouldn't write them.
func (*BidiStream) ResponseTrailer ¶
func (b *BidiStream) ResponseTrailer() http.Header
ResponseTrailer returns the response trailers. Handlers may write to the response trailers at any time before returning.
Trailers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols. Applications shouldn't write them.
func (*BidiStream) Send ¶
func (b *BidiStream) Send(msg interface{}) error
Send a message to the client. The first call to Send also sends the response headers.
func (*BidiStream) Spec ¶
func (b *BidiStream) Spec() Spec
Spec returns the specification for the RPC.
type BidiStreamForClient ¶
type BidiStreamForClient struct {
// contains filtered or unexported fields
}
BidiStreamForClient is the client's view of a bidirectional streaming RPC.
It's returned from Client.CallBidiStream, but doesn't currently have an exported constructor function.
func (*BidiStreamForClient) CloseRequest ¶
func (b *BidiStreamForClient) CloseRequest() error
CloseRequest closes the send side of the stream.
func (*BidiStreamForClient) CloseResponse ¶
func (b *BidiStreamForClient) CloseResponse() error
CloseResponse closes the receive side of the stream.
func (*BidiStreamForClient) Conn ¶
func (b *BidiStreamForClient) Conn() (StreamingClientConn, error)
Conn exposes the underlying StreamingClientConn. This may be useful if you'd prefer to wrap the connection in a different high-level API.
func (*BidiStreamForClient) Peer ¶
func (b *BidiStreamForClient) Peer() Peer
Peer describes the server for the RPC.
func (*BidiStreamForClient) Receive ¶
func (b *BidiStreamForClient) Receive(msg interface{}) error
Receive a message. When the server is done sending messages and no other errors have occurred, Receive will return an error that wraps io.EOF.
func (*BidiStreamForClient) RequestHeader ¶
func (b *BidiStreamForClient) RequestHeader() http.Header
RequestHeader returns the request headers. Headers are sent with the first call to Send.
Headers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols. Applications shouldn't write them.
func (*BidiStreamForClient) ResponseHeader ¶
func (b *BidiStreamForClient) ResponseHeader() http.Header
ResponseHeader returns the headers received from the server. It blocks until the first call to Receive returns.
func (*BidiStreamForClient) ResponseTrailer ¶
func (b *BidiStreamForClient) ResponseTrailer() http.Header
ResponseTrailer returns the trailers received from the server. Trailers aren't fully populated until Receive() returns an error wrapping io.EOF.
func (*BidiStreamForClient) Send ¶
func (b *BidiStreamForClient) Send(msg interface{}) error
Send a message to the server. The first call to Send also sends the request headers. To send just the request headers without a body, call Send with a nil pointer.
If the server returns an error, Send returns an error that wraps io.EOF. Clients should check for EOF using the standard library's errors.Is and call Receive to retrieve the error.
func (*BidiStreamForClient) Spec ¶
func (b *BidiStreamForClient) Spec() Spec
Spec returns the specification for the RPC.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a reusable, concurrency-safe client for a single procedure. Depending on the procedure's type, use the CallUnary, CallClientStream, CallServerStream, or CallBidiStream method.
By default, clients use the gRPC protocol with the binary Protobuf Codec, ask for gzipped responses, and send uncompressed requests. To use the Triple, use the WithTriple options.
func NewClient ¶
func NewClient(httpClient HTTPClient, url string, options ...ClientOption) *Client
NewClient constructs a new Client.
func (*Client) CallBidiStream ¶
func (c *Client) CallBidiStream(ctx context.Context) (*BidiStreamForClient, error)
CallBidiStream calls a bidirectional streaming procedure.
func (*Client) CallClientStream ¶
func (c *Client) CallClientStream(ctx context.Context) (*ClientStreamForClient, error)
CallClientStream calls a client streaming procedure.
func (*Client) CallServerStream ¶
func (c *Client) CallServerStream(ctx context.Context, request *Request) (*ServerStreamForClient, error)
CallServerStream calls a server streaming procedure.
type ClientOption ¶
type ClientOption interface {
// contains filtered or unexported methods
}
A ClientOption configures a Client.
In addition to any options grouped in the documentation below, remember that any Option is also a valid ClientOption.
func WithAcceptCompression ¶
func WithAcceptCompression( name string, newDecompressor func() Decompressor, newCompressor func() Compressor, ) ClientOption
WithAcceptCompression makes a compression algorithm available to a client. Clients ask servers to compress responses using any of the registered algorithms. The first registered algorithm is treated as the least preferred, and the last registered algorithm is the most preferred.
It's safe to use this option liberally: servers will ignore any compression algorithms they don't support. To compress requests, pair this option with WithSendCompression. To remove support for a previously-registered compression algorithm, use WithAcceptCompression with nil decompressor and compressor constructors.
Clients accept gzipped responses by default, using a compressor backed by the standard library's gzip package with the default compression level. Use WithSendGzip to compress requests with gzip.
Calling WithAcceptCompression with an empty name is a no-op.
func WithClientOptions ¶
func WithClientOptions(options ...ClientOption) ClientOption
WithClientOptions composes multiple ClientOptions into one.
func WithMsgPack ¶
func WithMsgPack() ClientOption
func WithProtoJSON ¶
func WithProtoJSON() ClientOption
WithProtoJSON configures a client to send JSON-encoded data instead of binary Protobuf. It uses the standard Protobuf JSON mapping as implemented by google.golang.org/protobuf/encoding/protojson: fields are named using lowerCamelCase, zero values are omitted, missing required fields are errors, enums are emitted as strings, etc.
func WithSendCompression ¶
func WithSendCompression(name string) ClientOption
WithSendCompression configures the client to use the specified algorithm to compress request messages. If the algorithm has not been registered using WithAcceptCompression, the client will return errors at runtime.
Because some servers don't support compression, clients default to sending uncompressed requests.
func WithSendGzip ¶
func WithSendGzip() ClientOption
WithSendGzip configures the client to gzip requests. Since clients have access to a gzip compressor by default, WithSendGzip doesn't require WithSendCompression.
Some servers don't support gzip, so clients default to sending uncompressed requests.
func WithTimeout ¶
func WithTimeout(timeout time.Duration) ClientOption
WithTimeout configures the default timeout of client call including unary and stream. If you want to specify the timeout of a specific request, please use context.WithTimeout, then default timeout would be overridden.
func WithTriple ¶
func WithTriple() ClientOption
WithTriple configures clients to use the Triple protocol.
type ClientStream ¶
type ClientStream struct {
// contains filtered or unexported fields
}
ClientStream is the handler's view of a client streaming RPC.
It's constructed as part of Handler invocation, but doesn't currently have an exported constructor.
func (*ClientStream) Conn ¶
func (c *ClientStream) Conn() StreamingHandlerConn
Conn exposes the underlying StreamingHandlerConn. This may be useful if you'd prefer to wrap the connection in a different high-level API.
func (*ClientStream) Err ¶
func (c *ClientStream) Err() error
Err returns the first non-EOF error that was encountered by Receive.
func (*ClientStream) Msg ¶
func (c *ClientStream) Msg() interface{}
Msg returns the most recent message unmarshaled by a call to Receive.
func (*ClientStream) Peer ¶
func (c *ClientStream) Peer() Peer
Peer describes the client for this RPC.
func (*ClientStream) Receive ¶
func (c *ClientStream) Receive(msg interface{}) bool
Receive advances the stream to the next message, which will then be available through the Msg method. It returns false when the stream stops, either by reaching the end or by encountering an unexpected error. After Receive returns false, the Err method will return any unexpected error encountered.
func (*ClientStream) RequestHeader ¶
func (c *ClientStream) RequestHeader() http.Header
RequestHeader returns the headers received from the client.
func (*ClientStream) Spec ¶
func (c *ClientStream) Spec() Spec
Spec returns the specification for the RPC.
type ClientStreamForClient ¶
type ClientStreamForClient struct {
// contains filtered or unexported fields
}
ClientStreamForClient is the client's view of a client streaming RPC.
It's returned from Client.CallClientStream, but doesn't currently have an exported constructor function.
func (*ClientStreamForClient) CloseAndReceive ¶
func (c *ClientStreamForClient) CloseAndReceive(response *Response) error
CloseAndReceive closes the send side of the stream and waits for the response.
func (*ClientStreamForClient) Conn ¶
func (c *ClientStreamForClient) Conn() (StreamingClientConn, error)
Conn exposes the underlying StreamingClientConn. This may be useful if you'd prefer to wrap the connection in a different high-level API.
func (*ClientStreamForClient) Peer ¶
func (c *ClientStreamForClient) Peer() Peer
Peer describes the server for the RPC.
func (*ClientStreamForClient) RequestHeader ¶
func (c *ClientStreamForClient) RequestHeader() http.Header
RequestHeader returns the request headers. Headers are sent to the server with the first call to Send.
Headers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols. Applications shouldn't write them.
func (*ClientStreamForClient) Send ¶
func (c *ClientStreamForClient) Send(request interface{}) error
Send a message to the server. The first call to Send also sends the request headers.
If the server returns an error, Send returns an error that wraps io.EOF. Clients should check for case using the standard library's errors.Is or IsEnded and unmarshal the error using CloseAndReceive.
func (*ClientStreamForClient) Spec ¶
func (c *ClientStreamForClient) Spec() Spec
Spec returns the specification for the RPC.
type Code ¶
type Code uint32
A Code is one of the Triple protocol's error codes. There are no user-defined codes, so only the codes enumerated below are valid. In both name and semantics, these codes match the gRPC status codes.
The descriptions below are optimized for brevity rather than completeness. See the [Triple protocol specification] for detailed descriptions of each code and example usage.
todo(DMwangnima): add specification to dubbo-go official site [Triple protocol specification]: https://connect.build/docs/protocol
const ( // CodeCanceled indicates that the operation was canceled, typically by the // caller. CodeCanceled Code = 1 // CodeUnknown indicates that the operation failed for an unknown reason. CodeUnknown Code = 2 // CodeInvalidArgument indicates that client supplied an invalid argument. CodeInvalidArgument Code = 3 // CodeDeadlineExceeded indicates that deadline expired before the operation // could complete. CodeDeadlineExceeded Code = 4 // CodeNotFound indicates that some requested entity (for example, a file or // directory) was not found. CodeNotFound Code = 5 // CodeAlreadyExists indicates that client attempted to create an entity (for // example, a file or directory) that already exists. CodeAlreadyExists Code = 6 // CodePermissionDenied indicates that the caller doesn't have permission to // execute the specified operation. CodePermissionDenied Code = 7 // CodeResourceExhausted indicates that some resource has been exhausted. For // example, a per-user quota may be exhausted or the entire file system may // be full. CodeResourceExhausted Code = 8 // CodeFailedPrecondition indicates that the system is not in a state // required for the operation's execution. CodeFailedPrecondition Code = 9 // CodeAborted indicates that operation was aborted by the system, usually // because of a concurrency issue such as a sequencer check failure or // transaction abort. CodeAborted Code = 10 // CodeOutOfRange indicates that the operation was attempted past the valid // range (for example, seeking past end-of-file). CodeOutOfRange Code = 11 // CodeUnimplemented indicates that the operation isn't implemented, // supported, or enabled in this service. CodeUnimplemented Code = 12 // CodeInternal indicates that some invariants expected by the underlying // system have been broken. This code is reserved for serious errors. CodeInternal Code = 13 // is usually temporary, so clients can back off and retry idempotent // operations. CodeUnavailable Code = 14 // CodeDataLoss indicates that the operation has resulted in unrecoverable // data loss or corruption. CodeDataLoss Code = 15 // CodeUnauthenticated indicates that the request does not have valid // authentication credentials for the operation. CodeUnauthenticated Code = 16 CodeBizError Code = 17 )
func CodeOf ¶
CodeOf returns the error's status code if it is or wraps an *Error and CodeUnknown otherwise.
func (Code) MarshalText ¶
MarshalText implements encoding.TextMarshaler.
func (*Code) UnmarshalText ¶
UnmarshalText implements encoding.TextUnmarshaler.
type Codec ¶
type Codec interface { // Name returns the name of the Codec. // // This may be used as part of the Content-Type within HTTP. For example, // with gRPC this is the content subtype, so "application/grpc+proto" will // map to the Codec with name "proto". // // Names must not be empty. Name() string // Marshal marshals the given message. // // Marshal may expect a specific type of message, and will error if this type // is not given. Marshal(interface{}) ([]byte, error) // Unmarshal unmarshals the given message. // // Unmarshal may expect a specific type of message, and will error if this // type is not given. Unmarshal([]byte, interface{}) error }
Codec marshals structs (typically generated from a schema) to and from bytes.
type Compressor ¶
type Compressor interface { io.Writer // Close flushes any buffered data to the underlying sink, then closes the // Compressor. It must not close the underlying sink. Close() error // Reset discards the Compressor's internal state, if any, and prepares it to // write compressed data to a new sink. Reset(io.Writer) }
A Compressor is a reusable wrapper that compresses data written to an underlying sink. The standard library's *gzip.Writer implements Compressor.
type Decompressor ¶
type Decompressor interface { io.Reader // Close closes the Decompressor, but not the underlying data source. It may // return an error if the Decompressor wasn't read to EOF. Close() error // Reset discards the Decompressor's internal state, if any, and prepares it // to read from a new source of compressed data. Reset(io.Reader) error }
A Decompressor is a reusable wrapper that decompresses an underlying data source. The standard library's *gzip.Reader implements Decompressor.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
An Error captures four key pieces of information: a Code, an underlying Go error, a map of metadata, and an optional collection of arbitrary Protobuf messages called "details" (more on those below). Servers send the code, the underlying error's Error() output, the metadata, and details over the wire to clients. Remember that the underlying error's message will be sent to clients - take care not to leak sensitive information from public APIs!
Service implementations and interceptors should return errors that can be cast to an *Error (using the standard library's errors.As). If the returned error can't be cast to an *Error, triple will use CodeUnknown and the returned error's message.
Error details are an optional mechanism for servers, interceptors, and proxies to attach arbitrary Protobuf messages to the error code and message. They're a clearer and more performant alternative to HTTP header microformats. See [the documentation on errors] for more details.
todo(DMwangnima): add error documentation to dubbo-go official website [the documentation on errors]: https://connect.build/docs/go/errors
func NewWireError ¶
NewWireError is similar to NewError, but the resulting *Error returns true when tested with IsWireError.
This is useful for clients trying to propagate partial failures from streaming RPCs. Often, these RPCs include error information in their response messages (for example, gRPC server reflection and OpenTelemtetry's OTLP). Clients propagating these errors up the stack should use NewWireError to clarify that the error code, message, and details (if any) were explicitly sent by the server rather than inferred from a lower-level networking error or timeout.
func (*Error) AddDetail ¶
func (e *Error) AddDetail(d *ErrorDetail)
AddDetail appends to the error's details.
func (*Error) Details ¶
func (e *Error) Details() []*ErrorDetail
Details returns the error's details.
func (*Error) Message ¶
Message returns the underlying error message. It may be empty if the original error was created with a status code and a nil error.
Example ¶
package main import ( "errors" "fmt" tri "gitee.com/git4chen/dubbo-go/protocol/triple/triple_protocol" ) func main() { err := fmt.Errorf( "another: %w", tri.NewError(tri.CodeUnavailable, errors.New("failed to foo")), ) if connectErr := (&tri.Error{}); errors.As(err, &connectErr) { fmt.Println("underlying error message:", connectErr.Message()) } }
Output: underlying error message: failed to foo
func (*Error) Meta ¶
Meta allows the error to carry additional information as key-value pairs.
Metadata attached to errors returned by unary handlers is always sent as HTTP headers, regardless of the protocol. Metadata attached to errors returned by streaming handlers may be sent as HTTP headers, HTTP trailers, or a block of in-body metadata, depending on the protocol in use and whether or not the handler has already written messages to the stream.
When clients receive errors, the metadata contains the union of the HTTP headers and the protocol-specific trailers (either HTTP trailers or in-body metadata).
type ErrorDetail ¶
type ErrorDetail struct {
// contains filtered or unexported fields
}
An ErrorDetail is a self-describing Protobuf message attached to an *Error. Error details are sent over the network to clients, which can then work with strongly-typed data rather than trying to parse a complex error message. For example, you might use details to send a localized error message or retry parameters to the client.
The google.golang.org/genproto/googleapis/rpc/errdetails package contains a variety of Protobuf messages commonly used as error details.
func NewErrorDetail ¶
func NewErrorDetail(msg proto.Message) (*ErrorDetail, error)
NewErrorDetail constructs a new error detail. If msg is an *anypb.Any then it is used as is. Otherwise, it is first marshaled into an *anypb.Any value. This returns an error if msg cannot be marshaled.
func (*ErrorDetail) Bytes ¶
func (d *ErrorDetail) Bytes() []byte
Bytes returns a copy of the Protobuf-serialized detail.
func (*ErrorDetail) Type ¶
func (d *ErrorDetail) Type() string
Type is the fully-qualified name of the detail's Protobuf message (for example, acme.foo.v1.FooDetail).
type ErrorWriter ¶
type ErrorWriter struct {
// contains filtered or unexported fields
}
An ErrorWriter writes errors to an http.ResponseWriter in the format expected by an RPC client. This is especially useful in server-side net/http middleware, where you may wish to handle requests from RPC and non-RPC clients with the same code.
ErrorWriters are safe to use concurrently.
Example ¶
package main import ( "errors" "io" "log" "net/http" ) import ( tri "gitee.com/git4chen/dubbo-go/protocol/triple/triple_protocol" ) // NewHelloHandler is an example HTTP handler. In a real application, it might // handle RPCs, requests for HTML, or anything else. func NewHelloHandler() http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) { io.WriteString(response, "Hello, world!") }) } // NewAuthenticatedHandler is an example of middleware that works with both RPC // and non-RPC clients. func NewAuthenticatedHandler(handler http.Handler) http.Handler { errorWriter := tri.NewErrorWriter() return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) { // Dummy authentication logic. if request.Header.Get("Token") == "super-secret" { handler.ServeHTTP(response, request) return } defer request.Body.Close() defer io.Copy(io.Discard, request.Body) if errorWriter.IsSupported(request) { // Send a protocol-appropriate error to RPC clients, so that they receive // the right code, message, and any metadata or error details. unauthenticated := tri.NewError(tri.CodeUnauthenticated, errors.New("invalid token")) errorWriter.Write(response, request, unauthenticated) } else { // Send an error to non-RPC clients. response.WriteHeader(http.StatusUnauthorized) io.WriteString(response, "invalid token") } }) } func main() { mux := http.NewServeMux() mux.Handle("/", NewHelloHandler()) srv := &http.Server{ Addr: ":8080", Handler: NewAuthenticatedHandler(mux), } if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatalln(err) } }
Output:
func NewErrorWriter ¶
func NewErrorWriter(opts ...HandlerOption) *ErrorWriter
NewErrorWriter constructs an ErrorWriter. To properly recognize supported RPC Content-Types in net/http middleware, you must pass the same HandlerOptions to NewErrorWriter and any wrapped Triple handlers.
func (*ErrorWriter) IsSupported ¶
func (w *ErrorWriter) IsSupported(request *http.Request) bool
IsSupported checks whether a request is using one of the ErrorWriter's supported RPC protocols.
func (*ErrorWriter) Write ¶
func (w *ErrorWriter) Write(response http.ResponseWriter, request *http.Request, err error) error
Write an error, using the format appropriate for the RPC protocol in use. Callers should first use IsSupported to verify that the request is using one of the ErrorWriter's supported RPC protocols.
Write does not read or close the request body.
type ExpectedCodecNameOption ¶
type ExpectedCodecNameOption struct {
ExpectedCodecName string
}
type HTTPClient ¶
HTTPClient is the interface triple expects HTTP clients to implement. The standard library's *http.Client implements HTTPClient.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
A Handler is the server-side implementation of a single RPC defined by a service schema.
By default, Handlers support the Triple, gRPC, and gRPC-Web protocols with the binary Protobuf and JSON codecs. They support gzip compression using the standard library's compress/gzip.
func NewBidiStreamHandler ¶
func NewBidiStreamHandler( procedure string, streamFunc func(context.Context, *BidiStream) error, options ...HandlerOption, ) *Handler
NewBidiStreamHandler constructs a Handler for a bidirectional streaming procedure.
func NewClientStreamHandler ¶
func NewClientStreamHandler( procedure string, streamFunc func(context.Context, *ClientStream) (*Response, error), options ...HandlerOption, ) *Handler
NewClientStreamHandler constructs a Handler for a client streaming procedure.
func NewCompatStreamHandler ¶
func NewCompatStreamHandler( procedure string, srv interface{}, typ StreamType, streamFunc func(srv interface{}, stream grpc.ServerStream) error, options ...HandlerOption, ) *Handler
func NewCompatUnaryHandler ¶
func NewCompatUnaryHandler( procedure string, method string, srv interface{}, unary MethodHandler, options ...HandlerOption, ) *Handler
func NewServerStreamHandler ¶
func NewServerStreamHandler( procedure string, reqInitFunc func() interface{}, streamFunc func(context.Context, *Request, *ServerStream) error, options ...HandlerOption, ) *Handler
NewServerStreamHandler constructs a Handler for a server streaming procedure.
func NewUnaryHandler ¶
func NewUnaryHandler( procedure string, reqInitFunc func() interface{}, unary func(context.Context, *Request) (*Response, error), options ...HandlerOption, ) *Handler
NewUnaryHandler constructs a Handler for a request-response procedure.
func (*Handler) ServeHTTP ¶
func (h *Handler) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request)
ServeHTTP implements http.Handler.
type HandlerOption ¶
type HandlerOption interface {
// contains filtered or unexported methods
}
A HandlerOption configures a Handler.
In addition to any options grouped in the documentation below, remember that any Option is also a HandlerOption.
func WithCompression ¶
func WithCompression( name string, newDecompressor func() Decompressor, newCompressor func() Compressor, ) HandlerOption
WithCompression configures handlers to support a compression algorithm. Clients may send messages compressed with that algorithm and/or request compressed responses. The Compressor and Decompressor produced by the supplied constructors must use the same algorithm. Internally, Triple pools compressors and decompressors.
By default, handlers support gzip using the standard library's compress/gzip package at the default compression level. To remove support for a previously-registered compression algorithm, use WithCompression with nil decompressor and compressor constructors.
Calling WithCompression with an empty name is a no-op.
func WithHandlerOptions ¶
func WithHandlerOptions(options ...HandlerOption) HandlerOption
WithHandlerOptions composes multiple HandlerOptions into one.
func WithRecover ¶
WithRecover adds an interceptor that recovers from panics. The supplied function receives the context, Spec, request headers, and the recovered value (which may be nil). It must return an error to send back to the client. It may also log the panic, emit metrics, or execute other error-handling logic. Handler functions must be safe to call concurrently.
To preserve compatibility with net/http's semantics, this interceptor doesn't handle panics with http.ErrAbortHandler.
By default, handlers don't recover from panics. Because the standard library's http.Server recovers from panics by default, this option isn't usually necessary to prevent crashes. Instead, it helps servers collect RPC-specific data during panics and send a more detailed error to clients.
func WithRequireTripleProtocolHeader ¶
func WithRequireTripleProtocolHeader() HandlerOption
WithRequireTripleProtocolHeader configures the Handler to require requests using the Triple RPC protocol to include the Triple-Protocol-Version header. This ensures that HTTP proxies and net/http middleware can easily identify valid Triple requests, even if they use a common Content-Type like application/json. However, it makes ad-hoc requests with tools like cURL more laborious.
This option has no effect if the client uses the gRPC or gRPC-Web protocols.
type IdempotencyLevel ¶
type IdempotencyLevel int
An IdempotencyLevel is a value that declares how "idempotent" an RPC is. This value can affect RPC behaviors, such as determining whether it is safe to retry a request, or what kinds of request modalities are allowed for a given procedure.
const ( // IdempotencyUnknown is the default idempotency level. A procedure with // this idempotency level may not be idempotent. This is appropriate for // any kind of procedure. IdempotencyUnknown IdempotencyLevel = 0 // IdempotencyNoSideEffects is the idempotency level that specifies that a // given call has no side-effects. This is equivalent to [RFC 9110 § 9.2.1] // "safe" methods in terms of semantics. This procedure should not mutate // any state. This idempotency level is appropriate for queries, or anything // that would be suitable for an HTTP GET request. In addition, due to the // lack of side-effects, such a procedure would be suitable to retry and // expect that the results will not be altered by preceding attempts. // // [RFC 9110 § 9.2.1]: https://www.rfc-editor.org/rfc/rfc9110.html#section-9.2.1 IdempotencyNoSideEffects IdempotencyLevel = 1 // IdempotencyIdempotent is the idempotency level that specifies that a // given call is "idempotent", such that multiple instances of the same // request to this procedure would have the same side-effects as a single // request. This is equivalent to [RFC 9110 § 9.2.2] "idempotent" methods. // This level is a subset of the previous level. This idempotency level is // appropriate for any procedure that is safe to retry multiple times // and be guaranteed that the response and side-effects will not be altered // as a result of multiple attempts, for example, entity deletion requests. // // [RFC 9110 § 9.2.2]: https://www.rfc-editor.org/rfc/rfc9110.html#section-9.2.2 IdempotencyIdempotent IdempotencyLevel = 2 )
func (IdempotencyLevel) String ¶
func (i IdempotencyLevel) String() string
type Interceptor ¶
type Interceptor interface { WrapUnary(UnaryFunc) UnaryFunc WrapUnaryHandler(UnaryHandlerFunc) UnaryHandlerFunc WrapStreamingClient(StreamingClientFunc) StreamingClientFunc WrapStreamingHandler(StreamingHandlerFunc) StreamingHandlerFunc }
An Interceptor adds logic to a generated handler or client, like the decorators or middleware you may have seen in other libraries. Interceptors may replace the context, mutate requests and responses, handle errors, retry, recover from panics, emit logs and metrics, or do nearly anything else.
The returned functions must be safe to call concurrently.
type MethodHandler ¶
type Option ¶
type Option interface { ClientOption HandlerOption }
Option implements both ClientOption and HandlerOption, so it can be applied both client-side and server-side.
func WithCodec ¶
WithCodec registers a serialization method with a client or handler. Handlers may have multiple codecs registered, and use whichever the client chooses. Clients may only have a single codec.
By default, handlers and clients support binary Protocol Buffer data using google.golang.org/protobuf/proto. Handlers also support JSON by default, using the standard Protobuf JSON mapping. Users with more specialized needs may override the default codecs by registering a new codec under the "proto" or "json" names. When supplying a custom "proto" codec, keep in mind that some unexported, protocol-specific messages are serialized using Protobuf - take care to fall back to the standard Protobuf implementation if necessary.
Registering a codec with an empty name is a no-op.
func WithCompressMinBytes ¶
WithCompressMinBytes sets a minimum size threshold for compression: regardless of compressor configuration, messages smaller than the configured minimum are sent uncompressed.
The default minimum is zero. Setting a minimum compression threshold may improve overall performance, because the CPU cost of compressing very small messages usually isn't worth the small reduction in network I/O.
func WithExpectedCodecName ¶
func WithIdempotency ¶
func WithIdempotency(idempotencyLevel IdempotencyLevel) Option
todo(DMwangnima): consider how to expose this functionality to users WithIdempotency declares the idempotency of the procedure. This can determine whether a procedure call can safely be retried, and may affect which request modalities are allowed for a given procedure call.
In most cases, you should not need to manually set this. It is normally set by the code generator for your schema. For protobuf schemas, it can be set like this:
rpc Ping(PingRequest) returns (PingResponse) { option idempotency_level = NO_SIDE_EFFECTS; }
func WithInterceptors ¶
func WithInterceptors(interceptors ...Interceptor) Option
WithInterceptors configures a client or handler's interceptor stack. Repeated WithInterceptors options are applied in order, so
WithInterceptors(A) + WithInterceptors(B, C) == WithInterceptors(A, B, C)
Unary interceptors compose like an onion. The first interceptor provided is the outermost layer of the onion: it acts first on the context and request, and last on the response and error.
Stream interceptors also behave like an onion: the first interceptor provided is the outermost wrapper for the StreamingClientConn or StreamingHandlerConn. It's the first to see sent messages and the last to see received messages.
Applied to client and handler, WithInterceptors(A, B, ..., Y, Z) produces:
client.Send() client.Receive() | ^ v | A --- --- A B --- --- B : ... ... : Y --- --- Y Z --- --- Z | ^ v | = = = = = = = = = = = = = = = = network = = = = = = = = = = = = = = = = | ^ v | A --- --- A B --- --- B : ... ... : Y --- --- Y Z --- --- Z | ^ v | handler.Receive() handler.Send() | ^ | | '-> handler logic >-'
Note that in clients, Send handles the request message(s) and Receive handles the response message(s). For handlers, it's the reverse. Depending on your interceptor's logic, you may need to wrap one method in clients and the other in handlers.
Example ¶
logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */) outer := triple.UnaryInterceptorFunc( func(next triple.UnaryFunc) triple.UnaryFunc { return triple.UnaryFunc(func(ctx context.Context, req triple.AnyRequest, res triple.AnyResponse) error { logger.Println("outer interceptor: before call") err := next(ctx, req, res) logger.Println("outer interceptor: after call") return err }) }, ) inner := triple.UnaryInterceptorFunc( func(next triple.UnaryFunc) triple.UnaryFunc { return triple.UnaryFunc(func(ctx context.Context, req triple.AnyRequest, res triple.AnyResponse) error { logger.Println("inner interceptor: before call") err := next(ctx, req, res) logger.Println("inner interceptor: after call") return err }) }, ) client := pingv1connect.NewPingServiceClient( examplePingServer.Client(), examplePingServer.URL(), triple.WithInterceptors(outer, inner), ) if err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{})); err != nil { logger.Println("error:", err) return }
Output: outer interceptor: before call inner interceptor: before call inner interceptor: after call outer interceptor: after call
func WithOptions ¶
WithOptions composes multiple Options into one.
func WithReadMaxBytes ¶
WithReadMaxBytes limits the performance impact of pathologically large messages sent by the other party. For handlers, WithReadMaxBytes limits the size of a message that the client can send. For clients, WithReadMaxBytes limits the size of a message that the server can respond with. Limits apply to each Protobuf message, not to the stream as a whole.
Setting WithReadMaxBytes to zero allows any message size. Both clients and handlers default to allowing any request size.
Handlers may also use http.MaxBytesHandler to limit the total size of the HTTP request stream (rather than the per-message size). Triple handles http.MaxBytesError specially, so clients still receive errors with the appropriate error code and informative messages.
func WithSendMaxBytes ¶
WithSendMaxBytes prevents sending messages too large for the client/handler to handle without significant performance overhead. For handlers, WithSendMaxBytes limits the size of a message that the handler can respond with. For clients, WithSendMaxBytes limits the size of a message that the client can send. Limits apply to each message, not to the stream as a whole.
Setting WithSendMaxBytes to zero allows any message size. Both clients and handlers default to allowing any message size.
func WithVersion ¶
type Peer ¶
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 ProtocolTriple, ProtocolGRPC, or todo: Should we support ProtocolGRPCWeb? 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.
type Request ¶
type Request struct { Msg interface{} // contains filtered or unexported fields }
Request is a wrapper around a generated request message. It provides access to metadata like headers and the RPC specification, as well as strongly-typed access to the message itself.
func NewRequest ¶
func NewRequest(message interface{}) *Request
NewRequest wraps a generated request message.
func (*Request) Any ¶
func (r *Request) Any() interface{}
Any returns the concrete request message as an empty interface, so that *Request implements the AnyRequest interface.
type Response ¶
type Response struct { Msg interface{} // contains filtered or unexported fields }
Response is a wrapper around a generated response message. It provides access to metadata like headers and trailers, as well as strongly-typed access to the message itself.
func NewResponse ¶
func NewResponse(message interface{}) *Response
NewResponse wraps a generated response message.
func (*Response) Any ¶
func (r *Response) Any() interface{}
Any returns the concrete response message as an empty interface, so that *Response implements the AnyResponse interface.
func (*Response) Header ¶
Header returns the HTTP headers for this response. Headers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols: applications may read them but shouldn't write them.
func (*Response) Trailer ¶
Trailer returns the trailers for this response. Depending on the underlying RPC protocol, trailers may be sent as HTTP trailers or a protocol-specific block of in-body metadata.
Trailers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols: applications may read them but shouldn't write them.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
func (*Server) RegisterBidiStreamHandler ¶
func (s *Server) RegisterBidiStreamHandler( procedure string, stream func(context.Context, *BidiStream) error, options ...HandlerOption, ) error
func (*Server) RegisterClientStreamHandler ¶
func (s *Server) RegisterClientStreamHandler( procedure string, stream func(context.Context, *ClientStream) (*Response, error), options ...HandlerOption, ) error
func (*Server) RegisterCompatStreamHandler ¶
func (s *Server) RegisterCompatStreamHandler( procedure string, srv interface{}, typ StreamType, streamFunc func(srv interface{}, stream grpc.ServerStream) error, options ...HandlerOption, ) error
func (*Server) RegisterCompatUnaryHandler ¶
func (s *Server) RegisterCompatUnaryHandler( procedure string, method string, srv interface{}, unary MethodHandler, options ...HandlerOption, ) error
func (*Server) RegisterServerStreamHandler ¶
func (s *Server) RegisterServerStreamHandler( procedure string, reqInitFunc func() interface{}, stream func(context.Context, *Request, *ServerStream) error, options ...HandlerOption, ) error
func (*Server) RegisterUnaryHandler ¶
type ServerStream ¶
type ServerStream struct {
// contains filtered or unexported fields
}
ServerStream is the handler's view of a server streaming RPC.
It's constructed as part of Handler invocation, but doesn't currently have an exported constructor.
func (*ServerStream) Conn ¶
func (s *ServerStream) Conn() StreamingHandlerConn
Conn exposes the underlying StreamingHandlerConn. This may be useful if you'd prefer to wrap the connection in a different high-level API.
func (*ServerStream) ResponseHeader ¶
func (s *ServerStream) ResponseHeader() http.Header
ResponseHeader returns the response headers. Headers are sent with the first call to Send.
Headers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols. Applications shouldn't write them.
func (*ServerStream) ResponseTrailer ¶
func (s *ServerStream) ResponseTrailer() http.Header
ResponseTrailer returns the response trailers. Handlers may write to the response trailers at any time before returning.
Trailers beginning with "Triple-" and "Grpc-" are reserved for use by the Triple and gRPC protocols. Applications shouldn't write them.
func (*ServerStream) Send ¶
func (s *ServerStream) Send(msg interface{}) error
Send a message to the client. The first call to Send also sends the response headers.
type ServerStreamForClient ¶
type ServerStreamForClient struct {
// contains filtered or unexported fields
}
ServerStreamForClient is the client's view of a server streaming RPC.
It's returned from Client.CallServerStream, but doesn't currently have an exported constructor function.
func (*ServerStreamForClient) Close ¶
func (s *ServerStreamForClient) Close() error
Close the receive side of the stream.
func (*ServerStreamForClient) Conn ¶
func (s *ServerStreamForClient) Conn() (StreamingClientConn, error)
Conn exposes the underlying StreamingClientConn. This may be useful if you'd prefer to wrap the connection in a different high-level API.
func (*ServerStreamForClient) Err ¶
func (s *ServerStreamForClient) Err() error
Err returns the first non-EOF error that was encountered by Receive.
func (*ServerStreamForClient) Msg ¶
func (s *ServerStreamForClient) Msg() interface{}
Msg returns the most recent message unmarshaled by a call to Receive.
func (*ServerStreamForClient) Receive ¶
func (s *ServerStreamForClient) Receive(msg interface{}) bool
Receive advances the stream to the next message, which will then be available through the Msg method. It returns false when the stream stops, either by reaching the end or by encountering an unexpected error. After Receive returns false, the Err method will return any unexpected error encountered. todo(DMwangnima): add classic usage
func (*ServerStreamForClient) ResponseHeader ¶
func (s *ServerStreamForClient) ResponseHeader() http.Header
ResponseHeader returns the headers received from the server. It blocks until the first call to Receive returns.
func (*ServerStreamForClient) ResponseTrailer ¶
func (s *ServerStreamForClient) ResponseTrailer() http.Header
ResponseTrailer returns the trailers received from the server. Trailers aren't fully populated until Receive() returns an error wrapping io.EOF.
type Spec ¶
type Spec struct { StreamType StreamType 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-triple-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 StreamType = 0b00 StreamTypeClient StreamType = 0b01 StreamTypeServer StreamType = 0b10 StreamTypeBidi = StreamTypeClient | StreamTypeServer )
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(interface{}) 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(interface{}) error ResponseHeader() http.Header ResponseTrailer() http.Header CloseResponse() error }
StreamingClientConn is the client's view of a bidirectional message exchange. Interceptors for streaming RPCs may wrap StreamingClientConn.
StreamingClientConn 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 or IsEnded. 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 "Triple-" and "Grpc-" are reserved for use by the gRPC and Triple 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.
type StreamingClientFunc ¶
type StreamingClientFunc func(context.Context, Spec) StreamingClientConn
StreamingClientFunc is the generic signature of a streaming RPC from the client's perspective. Interceptors may wrap StreamingClientFuncs.
type StreamingHandlerConn ¶
type StreamingHandlerConn interface { Spec() Spec Peer() Peer Receive(interface{}) error RequestHeader() http.Header ExportableHeader() http.Header Send(interface{}) 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 "Triple-" and "Grpc-" are reserved for use by the gRPC and Triple 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.
type StreamingHandlerFunc ¶
type StreamingHandlerFunc func(context.Context, StreamingHandlerConn) error
StreamingHandlerFunc is the generic signature of a streaming RPC from the handler's perspective. Interceptors may wrap StreamingHandlerFuncs.
type UnaryFunc ¶
type UnaryFunc func(context.Context, AnyRequest, AnyResponse) error
UnaryFunc is the generic signature of a unary RPC. Interceptors may wrap Funcs.
The type of the request and response structs depend on the codec being used. When using Protobuf, request.Any() and response.Any() will always be [proto.Message] implementations.
type UnaryHandlerFunc ¶
type UnaryHandlerFunc func(ctx context.Context, request AnyRequest) (AnyResponse, error)
UnaryHandlerFunc is the generic signature of a unary RPC from the handler's perspective. Interceptors may wrap UnaryHandlerFuncs.
type UnaryInterceptorFunc ¶
UnaryInterceptorFunc is a simple Interceptor implementation that only wraps unary RPCs from client's perspective. It has no effect on server side unary RPC and streaming RPCs.
Example ¶
logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */) loggingInterceptor := triple.UnaryInterceptorFunc( func(next triple.UnaryFunc) triple.UnaryFunc { return triple.UnaryFunc(func(ctx context.Context, request triple.AnyRequest, response triple.AnyResponse) error { logger.Println("calling:", request.Spec().Procedure) logger.Println("request:", request.Any()) err := next(ctx, request, response) if err != nil { logger.Println("error:", err) } else { logger.Println("response:", response.Any()) } return err }) }, ) client := pingv1connect.NewPingServiceClient( examplePingServer.Client(), examplePingServer.URL(), triple.WithInterceptors(loggingInterceptor), ) if err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Number: 42}), triple.NewResponse(&pingv1.PingResponse{})); err != nil { logger.Println("error:", err) return }
Output: calling: /connect.ping.v1.PingService/Ping request: number:42 response: number:42
func (UnaryInterceptorFunc) WrapStreamingClient ¶
func (f UnaryInterceptorFunc) WrapStreamingClient(next StreamingClientFunc) StreamingClientFunc
WrapStreamingClient implements Interceptor with a no-op.
func (UnaryInterceptorFunc) WrapStreamingHandler ¶
func (f UnaryInterceptorFunc) WrapStreamingHandler(next StreamingHandlerFunc) StreamingHandlerFunc
WrapStreamingHandler implements Interceptor with a no-op.
func (UnaryInterceptorFunc) WrapUnary ¶
func (f UnaryInterceptorFunc) WrapUnary(next UnaryFunc) UnaryFunc
WrapUnary implements Interceptor by applying the interceptor function.
func (UnaryInterceptorFunc) WrapUnaryHandler ¶
func (f UnaryInterceptorFunc) WrapUnaryHandler(next UnaryHandlerFunc) UnaryHandlerFunc
WrapUnaryHandler implements Interceptor with a no-op.
Source Files
¶
- buffer_pool.go
- client.go
- client_stream.go
- code.go
- codec.go
- compression.go
- duplex_http_call.go
- envelope.go
- error.go
- error_writer.go
- handler.go
- handler_compat.go
- handler_stream.go
- handler_stream_compat.go
- header.go
- header_compat.go
- idempotency_level.go
- interceptor.go
- maxbytes.go
- option.go
- protobuf_util.go
- protocol.go
- protocol_grpc.go
- protocol_triple.go
- recover.go
- server.go
- triple.go
Directories
¶
Path | Synopsis |
---|---|
internal
|
|
assert
Package assert is a minimal assert package using reflection.
|
Package assert is a minimal assert package using reflection. |
gen/proto/connect/ping/v1/pingv1connect
The connect.ping.v1 package contains an echo service designed to test the connect-go implementation.
|
The connect.ping.v1 package contains an echo service designed to test the connect-go implementation. |