Documentation
¶
Overview ¶
Package vanguardgrpc provides convenience functions to make it easy to wrap your grpc.Server with a vanguard.Transcoder, to upgrade it to supporting Connect, gRPC-Web, and REST+JSON protocols.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewCodec ¶
NewCodec returns a gRPC encoding.Codec that uses the given Vanguard Codec as its backing implementation. In particular, this can be combined with vanguard.JSONCodec to easily create a gRPC Codec to support the "json" message format.
func NewTranscoder ¶
func NewTranscoder(server *grpc.Server, opts ...vanguard.TranscoderOption) (*vanguard.Transcoder, error)
NewTranscoder returns a Vanguard handler that wraps the given gRPC server. All services registered with the server will be supported by the returned handler. The Vanguard handler will be configured to transcode incoming requests to the gRPC protocol.
The returned handler will allow data in the "proto" codec through, but must transcode other codecs to "proto". If a gRPC Codec has been registered with the name "json" (via encoding.RegisterCodec) then the Vanguard handler will pass JSON requests through unchanged as well.
For maximum efficiency, especially if REST and/or Connect clients are expected, a JSON codec should be registered before calling this function. If the server program does not already register such a codec, it may do so via the following:
encoding.RegisterCodec(vanguardgrpc.NewCodec(&vanguard.JSONCodec{ // These fields can be used to customize the serialization and // de-serialization behavior. The options presented below are // highly recommended. MarshalOptions: protojson.MarshalOptions{ EmitUnpopulated: true, }, UnmarshalOptions: protojson.UnmarshalOptions{ DiscardUnknown: true, }, })
Example (ConnectToGRPC) ¶
package main import ( "context" "log" "net/http/httptest" "os" "strings" "time" "connectrpc.com/connect" "connectrpc.com/vanguard" testv1 "connectrpc.com/vanguard/internal/gen/vanguard/test/v1" "connectrpc.com/vanguard/internal/gen/vanguard/test/v1/testv1connect" "connectrpc.com/vanguard/vanguardgrpc" "google.golang.org/grpc" "google.golang.org/grpc/encoding" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/timestamppb" ) func main() { log := log.New(os.Stdout, "" /* prefix */, 0 /* flags */) // Configure gRPC servers to support JSON. encoding.RegisterCodec(vanguardgrpc.NewCodec(&vanguard.JSONCodec{ MarshalOptions: protojson.MarshalOptions{EmitUnpopulated: true}, UnmarshalOptions: protojson.UnmarshalOptions{DiscardUnknown: true}, })) // Now create a gRPC server that provides the test LibraryService. svc := &libraryRPC{} grpcServer := grpc.NewServer() testv1.RegisterLibraryServiceServer(grpcServer, svc) // Create a vanguard handler for all services registered in grpcServer handler, err := vanguardgrpc.NewTranscoder(grpcServer) if err != nil { log.Println("error:", err) return } // Create the server. // (This is a httptest.Server, but it could be any http.Server) server := httptest.NewUnstartedServer(handler) server.EnableHTTP2 = true // HTTP/2 required for gRPC server.StartTLS() defer server.Close() // Create a connect client and call the service. client := testv1connect.NewLibraryServiceClient(server.Client(), server.URL, connect.WithProtoJSON()) // Call the service using Connect, translated by the middleware to gRPC. rsp, err := client.GetBook( context.Background(), connect.NewRequest(&testv1.GetBookRequest{ Name: "shelves/top/books/1", }), ) if err != nil { log.Println("error:", err) return } log.Println(rsp.Msg.Title) } type libraryRPC struct { testv1.UnimplementedLibraryServiceServer } func (s *libraryRPC) GetBook(_ context.Context, req *testv1.GetBookRequest) (*testv1.Book, error) { return &testv1.Book{ Name: req.Name, Parent: strings.Join(strings.Split(req.Name, "/")[:2], "/"), CreateTime: timestamppb.New(time.Date(1968, 1, 1, 0, 0, 0, 0, time.UTC)), Title: "Do Androids Dream of Electric Sheep?", Author: "Philip K. Dick", Description: "Have you seen Blade Runner?", Labels: map[string]string{ "genre": "science fiction", }, }, nil } func (s *libraryRPC) CreateBook(_ context.Context, req *testv1.CreateBookRequest) (*testv1.Book, error) { book := req.Book return &testv1.Book{ Name: strings.Join([]string{req.Parent, "books", req.BookId}, "/"), Parent: req.Parent, CreateTime: timestamppb.New(time.Date(1968, 1, 1, 0, 0, 0, 0, time.UTC)), Title: book.GetTitle(), Author: book.GetAuthor(), Description: book.GetDescription(), Labels: book.GetLabels(), }, nil }
Output: Do Androids Dream of Electric Sheep?
Types ¶
This section is empty.