├── .gitignore ├── 01-unary_rpc_example ├── buf.gen.yaml ├── client │ └── main.go ├── ecommerce │ ├── product.pb.go │ └── product_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ ├── buf.yaml │ └── product.proto └── server │ ├── main.go │ └── order.go ├── 02-server_streaming_rpc_example ├── buf.gen.yaml ├── client │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ ├── buf.yaml │ └── order.proto └── server │ ├── main.go │ └── order.go ├── 03-client_streaming_rpc_example ├── buf.gen.yaml ├── client │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ ├── buf.yaml │ └── order.proto └── server │ ├── main.go │ └── order.go ├── 04-bidirectional_streaming_rpc_example ├── buf.gen.yaml ├── client │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ ├── buf.yaml │ └── order.proto └── server │ ├── main.go │ └── order.go ├── 05-all_in_one_rpc_example ├── buf.gen.yaml ├── client │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ ├── buf.yaml │ └── order.proto └── server │ ├── main.go │ └── order.go ├── 06-interceptors ├── buf.gen.yaml ├── client │ ├── interceptor.go │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ ├── buf.yaml │ └── order.proto └── server │ ├── interceptor.go │ ├── main.go │ └── order.go ├── 07-error_handling ├── buf.gen.yaml ├── client │ └── main.go ├── common │ └── errors.go ├── ecommerce │ ├── product.pb.go │ └── product_grpc.pb.go ├── go.mod ├── go.sum ├── inner │ └── main.go ├── pb │ ├── buf.yaml │ └── product.proto └── server │ ├── main.go │ └── order.go ├── 08-metadata ├── client │ ├── interceptor.go │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ └── order.proto └── server │ ├── main.go │ └── order.go ├── 09-timeout ├── client │ ├── interceptor.go │ └── main.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ └── order.proto └── server │ ├── interceptor.go │ ├── main.go │ └── order.go ├── 10-secure ├── client │ └── main.go ├── ecommerce │ ├── product.pb.go │ └── product_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ └── product.proto ├── server │ ├── main.go │ └── order.go └── x509 │ ├── client.crt │ ├── client.csr │ ├── client.key │ ├── conf │ └── openssl.cnf │ ├── rootCA.srl │ ├── rootCa.crt │ ├── rootCa.key │ ├── server.crt │ ├── server.csr │ └── server.key ├── 11-authentication ├── 00-basic-authentication │ ├── client │ │ └── main.go │ └── server │ │ ├── main.go │ │ └── order.go ├── 01-jwt │ ├── client │ │ └── main.go │ └── server │ │ ├── main.go │ │ └── order.go ├── ecommerce │ ├── product.pb.go │ └── product_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ └── product.proto └── x509 │ ├── client.crt │ ├── client.csr │ ├── client.key │ ├── conf │ └── openssl.cnf │ ├── rootCA.srl │ ├── rootCa.crt │ ├── rootCa.key │ ├── server.crt │ ├── server.csr │ ├── server.key │ └── winged-axon-372312-154a8b3aa89d.json ├── 12-name_resolver ├── client │ ├── balancer │ │ ├── builder.go │ │ └── picker.go │ ├── main.go │ └── resolver │ │ ├── builder.go │ │ └── resolver.go ├── ecommerce │ ├── order.pb.go │ └── order_grpc.pb.go ├── go.mod ├── go.sum ├── pb │ └── order.proto ├── server │ ├── main.go │ └── order.go └── xds_client │ └── main.go ├── 13-ecosystem └── grpc-gateway │ ├── buf.gen.yaml │ ├── client │ └── main.go │ ├── doc │ ├── ecommerce │ │ ├── product.swagger.json │ │ └── v1 │ │ │ └── product.swagger.json │ └── product.swagger.json │ ├── ecommerce │ ├── product.pb.go │ ├── product.pb.gw.go │ └── product_grpc.pb.go │ ├── go.mod │ ├── go.sum │ ├── pb │ ├── buf.lock │ ├── buf.yaml │ └── product.proto │ ├── server │ ├── main.go │ └── order.go │ └── server2 │ ├── main.go │ └── order.go ├── LICENSE ├── README.md └── weixin.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | .DS_Store -------------------------------------------------------------------------------- /01-unary_rpc_example/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative -------------------------------------------------------------------------------- /01-unary_rpc_example/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | pb "github.com/liangwt/note/grpc/unary_rpc_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("127.0.0.1:8009", grpc.WithInsecure()) 15 | if err != nil { 16 | panic(err) 17 | } 18 | defer conn.Close() 19 | 20 | client := pb.NewOrderManagementClient(conn) 21 | 22 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 23 | defer cancel() 24 | 25 | // Add Order 26 | order := pb.Order{Id: "101", Items: []string{"iPhone XS", "Mac Book Pro"}, Destination: "San Jose, CA", Price: 2300.00} 27 | res, err := client.AddOrder(ctx, &order) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | log.Print("AddOrder Response -> ", res.Value) 33 | 34 | // Get Order 35 | retrievedOrder, err := client.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | log.Print("GetOrder Response -> : ", retrievedOrder) 41 | } 42 | -------------------------------------------------------------------------------- /01-unary_rpc_example/ecommerce/product_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: product.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) 27 | GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) 28 | } 29 | 30 | type orderManagementClient struct { 31 | cc grpc.ClientConnInterface 32 | } 33 | 34 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 35 | return &orderManagementClient{cc} 36 | } 37 | 38 | func (c *orderManagementClient) AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { 39 | out := new(wrapperspb.StringValue) 40 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/addOrder", in, out, opts...) 41 | if err != nil { 42 | return nil, err 43 | } 44 | return out, nil 45 | } 46 | 47 | func (c *orderManagementClient) GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) { 48 | out := new(Order) 49 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/getOrder", in, out, opts...) 50 | if err != nil { 51 | return nil, err 52 | } 53 | return out, nil 54 | } 55 | 56 | // OrderManagementServer is the server API for OrderManagement service. 57 | // All implementations must embed UnimplementedOrderManagementServer 58 | // for forward compatibility 59 | type OrderManagementServer interface { 60 | AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) 61 | GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) 62 | mustEmbedUnimplementedOrderManagementServer() 63 | } 64 | 65 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 66 | type UnimplementedOrderManagementServer struct { 67 | } 68 | 69 | func (UnimplementedOrderManagementServer) AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) { 70 | return nil, status.Errorf(codes.Unimplemented, "method AddOrder not implemented") 71 | } 72 | func (UnimplementedOrderManagementServer) GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) { 73 | return nil, status.Errorf(codes.Unimplemented, "method GetOrder not implemented") 74 | } 75 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 76 | 77 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 78 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 79 | // result in compilation errors. 80 | type UnsafeOrderManagementServer interface { 81 | mustEmbedUnimplementedOrderManagementServer() 82 | } 83 | 84 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 85 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 86 | } 87 | 88 | func _OrderManagement_AddOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 89 | in := new(Order) 90 | if err := dec(in); err != nil { 91 | return nil, err 92 | } 93 | if interceptor == nil { 94 | return srv.(OrderManagementServer).AddOrder(ctx, in) 95 | } 96 | info := &grpc.UnaryServerInfo{ 97 | Server: srv, 98 | FullMethod: "/ecommerce.OrderManagement/addOrder", 99 | } 100 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 101 | return srv.(OrderManagementServer).AddOrder(ctx, req.(*Order)) 102 | } 103 | return interceptor(ctx, in, info, handler) 104 | } 105 | 106 | func _OrderManagement_GetOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 107 | in := new(wrapperspb.StringValue) 108 | if err := dec(in); err != nil { 109 | return nil, err 110 | } 111 | if interceptor == nil { 112 | return srv.(OrderManagementServer).GetOrder(ctx, in) 113 | } 114 | info := &grpc.UnaryServerInfo{ 115 | Server: srv, 116 | FullMethod: "/ecommerce.OrderManagement/getOrder", 117 | } 118 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 119 | return srv.(OrderManagementServer).GetOrder(ctx, req.(*wrapperspb.StringValue)) 120 | } 121 | return interceptor(ctx, in, info, handler) 122 | } 123 | 124 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 125 | // It's only intended for direct use with grpc.RegisterService, 126 | // and not to be introspected or modified (even as a copy) 127 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 128 | ServiceName: "ecommerce.OrderManagement", 129 | HandlerType: (*OrderManagementServer)(nil), 130 | Methods: []grpc.MethodDesc{ 131 | { 132 | MethodName: "addOrder", 133 | Handler: _OrderManagement_AddOrder_Handler, 134 | }, 135 | { 136 | MethodName: "getOrder", 137 | Handler: _OrderManagement_GetOrder_Handler, 138 | }, 139 | }, 140 | Streams: []grpc.StreamDesc{}, 141 | Metadata: "product.proto", 142 | } 143 | -------------------------------------------------------------------------------- /01-unary_rpc_example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/unary_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 // indirect 7 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 8 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 9 | golang.org/x/text v0.3.0 // indirect 10 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 11 | ) 12 | 13 | require ( 14 | google.golang.org/grpc v1.44.0 15 | google.golang.org/protobuf v1.26.0 16 | ) 17 | -------------------------------------------------------------------------------- /01-unary_rpc_example/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /01-unary_rpc_example/pb/product.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | service OrderManagement { 10 | rpc addOrder(Order) returns (google.protobuf.StringValue); 11 | rpc getOrder(google.protobuf.StringValue) returns (Order); 12 | } 13 | 14 | message Order { 15 | string id = 1; 16 | repeated string items = 2; 17 | string description = 3; 18 | float price = 4; 19 | string destination = 5; 20 | } 21 | 22 | message CombinedShipment { 23 | string id = 1; 24 | string status = 2; 25 | repeated Order ordersList = 3; 26 | } -------------------------------------------------------------------------------- /01-unary_rpc_example/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/unary_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | 13 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 14 | 15 | lis, err := net.Listen("tcp", ":8009") 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | if err := s.Serve(lis); err != nil { 21 | panic(err) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /01-unary_rpc_example/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/unary_rpc_example/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 14 | 15 | var orders = make(map[string]pb.Order) 16 | 17 | type OrderManagementImpl struct { 18 | pb.UnimplementedOrderManagementServer 19 | } 20 | 21 | // Simple RPC 22 | func (s *OrderManagementImpl) AddOrder(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 23 | log.Printf("Order Added. ID : %v", orderReq.Id) 24 | orders[orderReq.Id] = *orderReq 25 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 26 | } 27 | 28 | // Simple RPC 29 | func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 30 | ord, exists := orders[orderId.Value] 31 | if exists { 32 | return &ord, status.New(codes.OK, "").Err() 33 | } 34 | 35 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 36 | 37 | } 38 | -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | 8 | pb "github.com/liangwt/note/grpc/server_streaming_rpc_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | func main(){ 14 | conn, err := grpc.Dial("127.0.0.1:8009", grpc.WithInsecure()) 15 | if err != nil{ 16 | panic(err) 17 | } 18 | 19 | c := pb.NewOrderManagementClient(conn) 20 | ctx, cancelFn := context.WithCancel(context.Background()) 21 | defer cancelFn() 22 | 23 | stream, err := c.SearchOrders(ctx, &wrapperspb.StringValue{Value: "Google"}) 24 | if err != nil{ 25 | panic(err) 26 | } 27 | 28 | for{ 29 | order, err := stream.Recv() 30 | if err == io.EOF{ 31 | break 32 | } 33 | 34 | log.Println("Search Result: ", order) 35 | } 36 | } -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/ecommerce/order.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc (unknown) 5 | // source: order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Order struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` 30 | Items []string `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` 31 | Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` 32 | Price float32 `protobuf:"fixed32,4,opt,name=price,proto3" json:"price,omitempty"` 33 | Destination string `protobuf:"bytes,5,opt,name=destination,proto3" json:"destination,omitempty"` 34 | } 35 | 36 | func (x *Order) Reset() { 37 | *x = Order{} 38 | if protoimpl.UnsafeEnabled { 39 | mi := &file_order_proto_msgTypes[0] 40 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 41 | ms.StoreMessageInfo(mi) 42 | } 43 | } 44 | 45 | func (x *Order) String() string { 46 | return protoimpl.X.MessageStringOf(x) 47 | } 48 | 49 | func (*Order) ProtoMessage() {} 50 | 51 | func (x *Order) ProtoReflect() protoreflect.Message { 52 | mi := &file_order_proto_msgTypes[0] 53 | if protoimpl.UnsafeEnabled && x != nil { 54 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 55 | if ms.LoadMessageInfo() == nil { 56 | ms.StoreMessageInfo(mi) 57 | } 58 | return ms 59 | } 60 | return mi.MessageOf(x) 61 | } 62 | 63 | // Deprecated: Use Order.ProtoReflect.Descriptor instead. 64 | func (*Order) Descriptor() ([]byte, []int) { 65 | return file_order_proto_rawDescGZIP(), []int{0} 66 | } 67 | 68 | func (x *Order) GetId() string { 69 | if x != nil { 70 | return x.Id 71 | } 72 | return "" 73 | } 74 | 75 | func (x *Order) GetItems() []string { 76 | if x != nil { 77 | return x.Items 78 | } 79 | return nil 80 | } 81 | 82 | func (x *Order) GetDescription() string { 83 | if x != nil { 84 | return x.Description 85 | } 86 | return "" 87 | } 88 | 89 | func (x *Order) GetPrice() float32 { 90 | if x != nil { 91 | return x.Price 92 | } 93 | return 0 94 | } 95 | 96 | func (x *Order) GetDestination() string { 97 | if x != nil { 98 | return x.Destination 99 | } 100 | return "" 101 | } 102 | 103 | var File_order_proto protoreflect.FileDescriptor 104 | 105 | var file_order_proto_rawDesc = []byte{ 106 | 0x0a, 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x65, 107 | 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 108 | 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 109 | 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 0x0a, 0x05, 0x4f, 0x72, 0x64, 110 | 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 111 | 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 112 | 0x09, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 113 | 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 114 | 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 115 | 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 116 | 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 117 | 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 118 | 0x6f, 0x6e, 0x32, 0x53, 0x0a, 0x0f, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 119 | 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0c, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4f, 120 | 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 121 | 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 122 | 0x6c, 0x75, 0x65, 0x1a, 0x10, 0x2e, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x2e, 123 | 0x4f, 0x72, 0x64, 0x65, 0x72, 0x30, 0x01, 0x42, 0x0c, 0x5a, 0x0a, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 124 | 0x65, 0x72, 0x63, 0x65, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 125 | } 126 | 127 | var ( 128 | file_order_proto_rawDescOnce sync.Once 129 | file_order_proto_rawDescData = file_order_proto_rawDesc 130 | ) 131 | 132 | func file_order_proto_rawDescGZIP() []byte { 133 | file_order_proto_rawDescOnce.Do(func() { 134 | file_order_proto_rawDescData = protoimpl.X.CompressGZIP(file_order_proto_rawDescData) 135 | }) 136 | return file_order_proto_rawDescData 137 | } 138 | 139 | var file_order_proto_msgTypes = make([]protoimpl.MessageInfo, 1) 140 | var file_order_proto_goTypes = []interface{}{ 141 | (*Order)(nil), // 0: ecommerce.Order 142 | (*wrapperspb.StringValue)(nil), // 1: google.protobuf.StringValue 143 | } 144 | var file_order_proto_depIdxs = []int32{ 145 | 1, // 0: ecommerce.OrderManagement.searchOrders:input_type -> google.protobuf.StringValue 146 | 0, // 1: ecommerce.OrderManagement.searchOrders:output_type -> ecommerce.Order 147 | 1, // [1:2] is the sub-list for method output_type 148 | 0, // [0:1] is the sub-list for method input_type 149 | 0, // [0:0] is the sub-list for extension type_name 150 | 0, // [0:0] is the sub-list for extension extendee 151 | 0, // [0:0] is the sub-list for field type_name 152 | } 153 | 154 | func init() { file_order_proto_init() } 155 | func file_order_proto_init() { 156 | if File_order_proto != nil { 157 | return 158 | } 159 | if !protoimpl.UnsafeEnabled { 160 | file_order_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 161 | switch v := v.(*Order); i { 162 | case 0: 163 | return &v.state 164 | case 1: 165 | return &v.sizeCache 166 | case 2: 167 | return &v.unknownFields 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | type x struct{} 174 | out := protoimpl.TypeBuilder{ 175 | File: protoimpl.DescBuilder{ 176 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 177 | RawDescriptor: file_order_proto_rawDesc, 178 | NumEnums: 0, 179 | NumMessages: 1, 180 | NumExtensions: 0, 181 | NumServices: 1, 182 | }, 183 | GoTypes: file_order_proto_goTypes, 184 | DependencyIndexes: file_order_proto_depIdxs, 185 | MessageInfos: file_order_proto_msgTypes, 186 | }.Build() 187 | File_order_proto = out.File 188 | file_order_proto_rawDesc = nil 189 | file_order_proto_goTypes = nil 190 | file_order_proto_depIdxs = nil 191 | } 192 | -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/ecommerce/order_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | SearchOrders(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (OrderManagement_SearchOrdersClient, error) 27 | } 28 | 29 | type orderManagementClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 34 | return &orderManagementClient{cc} 35 | } 36 | 37 | func (c *orderManagementClient) SearchOrders(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (OrderManagement_SearchOrdersClient, error) { 38 | stream, err := c.cc.NewStream(ctx, &OrderManagement_ServiceDesc.Streams[0], "/ecommerce.OrderManagement/searchOrders", opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | x := &orderManagementSearchOrdersClient{stream} 43 | if err := x.ClientStream.SendMsg(in); err != nil { 44 | return nil, err 45 | } 46 | if err := x.ClientStream.CloseSend(); err != nil { 47 | return nil, err 48 | } 49 | return x, nil 50 | } 51 | 52 | type OrderManagement_SearchOrdersClient interface { 53 | Recv() (*Order, error) 54 | grpc.ClientStream 55 | } 56 | 57 | type orderManagementSearchOrdersClient struct { 58 | grpc.ClientStream 59 | } 60 | 61 | func (x *orderManagementSearchOrdersClient) Recv() (*Order, error) { 62 | m := new(Order) 63 | if err := x.ClientStream.RecvMsg(m); err != nil { 64 | return nil, err 65 | } 66 | return m, nil 67 | } 68 | 69 | // OrderManagementServer is the server API for OrderManagement service. 70 | // All implementations must embed UnimplementedOrderManagementServer 71 | // for forward compatibility 72 | type OrderManagementServer interface { 73 | SearchOrders(*wrapperspb.StringValue, OrderManagement_SearchOrdersServer) error 74 | mustEmbedUnimplementedOrderManagementServer() 75 | } 76 | 77 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 78 | type UnimplementedOrderManagementServer struct { 79 | } 80 | 81 | func (UnimplementedOrderManagementServer) SearchOrders(*wrapperspb.StringValue, OrderManagement_SearchOrdersServer) error { 82 | return status.Errorf(codes.Unimplemented, "method SearchOrders not implemented") 83 | } 84 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 85 | 86 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 87 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 88 | // result in compilation errors. 89 | type UnsafeOrderManagementServer interface { 90 | mustEmbedUnimplementedOrderManagementServer() 91 | } 92 | 93 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 94 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 95 | } 96 | 97 | func _OrderManagement_SearchOrders_Handler(srv interface{}, stream grpc.ServerStream) error { 98 | m := new(wrapperspb.StringValue) 99 | if err := stream.RecvMsg(m); err != nil { 100 | return err 101 | } 102 | return srv.(OrderManagementServer).SearchOrders(m, &orderManagementSearchOrdersServer{stream}) 103 | } 104 | 105 | type OrderManagement_SearchOrdersServer interface { 106 | Send(*Order) error 107 | grpc.ServerStream 108 | } 109 | 110 | type orderManagementSearchOrdersServer struct { 111 | grpc.ServerStream 112 | } 113 | 114 | func (x *orderManagementSearchOrdersServer) Send(m *Order) error { 115 | return x.ServerStream.SendMsg(m) 116 | } 117 | 118 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 119 | // It's only intended for direct use with grpc.RegisterService, 120 | // and not to be introspected or modified (even as a copy) 121 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 122 | ServiceName: "ecommerce.OrderManagement", 123 | HandlerType: (*OrderManagementServer)(nil), 124 | Methods: []grpc.MethodDesc{}, 125 | Streams: []grpc.StreamDesc{ 126 | { 127 | StreamName: "searchOrders", 128 | Handler: _OrderManagement_SearchOrders_Handler, 129 | ServerStreams: true, 130 | }, 131 | }, 132 | Metadata: "order.proto", 133 | } 134 | -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/server_streaming_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.27.1 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.0 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | string destination = 5; 15 | } 16 | 17 | service OrderManagement { 18 | rpc searchOrders(google.protobuf.StringValue) returns (stream Order); 19 | } -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/server_streaming_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | 13 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 14 | 15 | lit, err := net.Listen("tcp", ":8009") 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | if err := s.Serve(lit); err != nil { 21 | panic(err) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /02-server_streaming_rpc_example/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | pb "github.com/liangwt/note/grpc/server_streaming_rpc_example/ecommerce" 8 | "google.golang.org/protobuf/types/known/wrapperspb" 9 | ) 10 | 11 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 12 | 13 | var orders = map[string]pb.Order{ 14 | "101": { 15 | Id: "101", 16 | Items: []string{ 17 | "Google", 18 | "Baidu", 19 | }, 20 | Description: "example", 21 | Price: 0, 22 | Destination: "example", 23 | }, 24 | } 25 | 26 | type OrderManagementImpl struct { 27 | pb.UnimplementedOrderManagementServer 28 | } 29 | 30 | func (s *OrderManagementImpl) SearchOrders(query *wrapperspb.StringValue, stram pb.OrderManagement_SearchOrdersServer) error { 31 | for _, order := range orders { 32 | for _, str := range order.Items { 33 | if strings.Contains(str, query.Value) { 34 | err := stram.Send(&order) 35 | if err != nil { 36 | return fmt.Errorf("error send: %v", err) 37 | } 38 | } 39 | } 40 | } 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func main() { 12 | conn, err := grpc.Dial("127.0.0.1:8009", grpc.WithInsecure()) 13 | if err != nil { 14 | panic(err) 15 | } 16 | 17 | c := pb.NewOrderManagementClient(conn) 18 | ctx, cancelFn := context.WithCancel(context.Background()) 19 | defer cancelFn() 20 | 21 | stream, err := c.UpdateOrders(ctx) 22 | if err != nil { 23 | panic(err) 24 | } 25 | 26 | if err := stream.Send(&pb.Order{ 27 | Id: "00", 28 | Items: []string{"A", "B"}, 29 | Description: "A with B", 30 | Price: 0.11, 31 | Destination: "ABC", 32 | }); err != nil { 33 | panic(err) 34 | } 35 | 36 | if err := stream.Send(&pb.Order{ 37 | Id: "01", 38 | Items: []string{"C", "D"}, 39 | Description: "C with D", 40 | Price: 1.11, 41 | Destination: "ABCDEFG", 42 | }); err != nil { 43 | panic(err) 44 | } 45 | 46 | res, err := stream.CloseAndRecv() 47 | if err != nil { 48 | panic(err) 49 | } 50 | 51 | log.Printf("Update Orders Res : %s", res) 52 | } 53 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/ecommerce/order.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc (unknown) 5 | // source: order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Order struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` 30 | Items []string `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` 31 | Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` 32 | Price float32 `protobuf:"fixed32,4,opt,name=price,proto3" json:"price,omitempty"` 33 | Destination string `protobuf:"bytes,5,opt,name=destination,proto3" json:"destination,omitempty"` 34 | } 35 | 36 | func (x *Order) Reset() { 37 | *x = Order{} 38 | if protoimpl.UnsafeEnabled { 39 | mi := &file_order_proto_msgTypes[0] 40 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 41 | ms.StoreMessageInfo(mi) 42 | } 43 | } 44 | 45 | func (x *Order) String() string { 46 | return protoimpl.X.MessageStringOf(x) 47 | } 48 | 49 | func (*Order) ProtoMessage() {} 50 | 51 | func (x *Order) ProtoReflect() protoreflect.Message { 52 | mi := &file_order_proto_msgTypes[0] 53 | if protoimpl.UnsafeEnabled && x != nil { 54 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 55 | if ms.LoadMessageInfo() == nil { 56 | ms.StoreMessageInfo(mi) 57 | } 58 | return ms 59 | } 60 | return mi.MessageOf(x) 61 | } 62 | 63 | // Deprecated: Use Order.ProtoReflect.Descriptor instead. 64 | func (*Order) Descriptor() ([]byte, []int) { 65 | return file_order_proto_rawDescGZIP(), []int{0} 66 | } 67 | 68 | func (x *Order) GetId() string { 69 | if x != nil { 70 | return x.Id 71 | } 72 | return "" 73 | } 74 | 75 | func (x *Order) GetItems() []string { 76 | if x != nil { 77 | return x.Items 78 | } 79 | return nil 80 | } 81 | 82 | func (x *Order) GetDescription() string { 83 | if x != nil { 84 | return x.Description 85 | } 86 | return "" 87 | } 88 | 89 | func (x *Order) GetPrice() float32 { 90 | if x != nil { 91 | return x.Price 92 | } 93 | return 0 94 | } 95 | 96 | func (x *Order) GetDestination() string { 97 | if x != nil { 98 | return x.Destination 99 | } 100 | return "" 101 | } 102 | 103 | var File_order_proto protoreflect.FileDescriptor 104 | 105 | var file_order_proto_rawDesc = []byte{ 106 | 0x0a, 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x65, 107 | 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 108 | 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 109 | 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 0x0a, 0x05, 0x4f, 0x72, 0x64, 110 | 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 111 | 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 112 | 0x09, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 113 | 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 114 | 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 115 | 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 116 | 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 117 | 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 118 | 0x6f, 0x6e, 0x32, 0x53, 0x0a, 0x0f, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 119 | 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 120 | 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x10, 0x2e, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 121 | 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 122 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 123 | 0x56, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x01, 0x42, 0x0c, 0x5a, 0x0a, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 124 | 0x65, 0x72, 0x63, 0x65, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 125 | } 126 | 127 | var ( 128 | file_order_proto_rawDescOnce sync.Once 129 | file_order_proto_rawDescData = file_order_proto_rawDesc 130 | ) 131 | 132 | func file_order_proto_rawDescGZIP() []byte { 133 | file_order_proto_rawDescOnce.Do(func() { 134 | file_order_proto_rawDescData = protoimpl.X.CompressGZIP(file_order_proto_rawDescData) 135 | }) 136 | return file_order_proto_rawDescData 137 | } 138 | 139 | var file_order_proto_msgTypes = make([]protoimpl.MessageInfo, 1) 140 | var file_order_proto_goTypes = []interface{}{ 141 | (*Order)(nil), // 0: ecommerce.Order 142 | (*wrapperspb.StringValue)(nil), // 1: google.protobuf.StringValue 143 | } 144 | var file_order_proto_depIdxs = []int32{ 145 | 0, // 0: ecommerce.OrderManagement.updateOrders:input_type -> ecommerce.Order 146 | 1, // 1: ecommerce.OrderManagement.updateOrders:output_type -> google.protobuf.StringValue 147 | 1, // [1:2] is the sub-list for method output_type 148 | 0, // [0:1] is the sub-list for method input_type 149 | 0, // [0:0] is the sub-list for extension type_name 150 | 0, // [0:0] is the sub-list for extension extendee 151 | 0, // [0:0] is the sub-list for field type_name 152 | } 153 | 154 | func init() { file_order_proto_init() } 155 | func file_order_proto_init() { 156 | if File_order_proto != nil { 157 | return 158 | } 159 | if !protoimpl.UnsafeEnabled { 160 | file_order_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 161 | switch v := v.(*Order); i { 162 | case 0: 163 | return &v.state 164 | case 1: 165 | return &v.sizeCache 166 | case 2: 167 | return &v.unknownFields 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | type x struct{} 174 | out := protoimpl.TypeBuilder{ 175 | File: protoimpl.DescBuilder{ 176 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 177 | RawDescriptor: file_order_proto_rawDesc, 178 | NumEnums: 0, 179 | NumMessages: 1, 180 | NumExtensions: 0, 181 | NumServices: 1, 182 | }, 183 | GoTypes: file_order_proto_goTypes, 184 | DependencyIndexes: file_order_proto_depIdxs, 185 | MessageInfos: file_order_proto_msgTypes, 186 | }.Build() 187 | File_order_proto = out.File 188 | file_order_proto_rawDesc = nil 189 | file_order_proto_goTypes = nil 190 | file_order_proto_depIdxs = nil 191 | } 192 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/ecommerce/order_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) 27 | } 28 | 29 | type orderManagementClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 34 | return &orderManagementClient{cc} 35 | } 36 | 37 | func (c *orderManagementClient) UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) { 38 | stream, err := c.cc.NewStream(ctx, &OrderManagement_ServiceDesc.Streams[0], "/ecommerce.OrderManagement/updateOrders", opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | x := &orderManagementUpdateOrdersClient{stream} 43 | return x, nil 44 | } 45 | 46 | type OrderManagement_UpdateOrdersClient interface { 47 | Send(*Order) error 48 | CloseAndRecv() (*wrapperspb.StringValue, error) 49 | grpc.ClientStream 50 | } 51 | 52 | type orderManagementUpdateOrdersClient struct { 53 | grpc.ClientStream 54 | } 55 | 56 | func (x *orderManagementUpdateOrdersClient) Send(m *Order) error { 57 | return x.ClientStream.SendMsg(m) 58 | } 59 | 60 | func (x *orderManagementUpdateOrdersClient) CloseAndRecv() (*wrapperspb.StringValue, error) { 61 | if err := x.ClientStream.CloseSend(); err != nil { 62 | return nil, err 63 | } 64 | m := new(wrapperspb.StringValue) 65 | if err := x.ClientStream.RecvMsg(m); err != nil { 66 | return nil, err 67 | } 68 | return m, nil 69 | } 70 | 71 | // OrderManagementServer is the server API for OrderManagement service. 72 | // All implementations must embed UnimplementedOrderManagementServer 73 | // for forward compatibility 74 | type OrderManagementServer interface { 75 | UpdateOrders(OrderManagement_UpdateOrdersServer) error 76 | mustEmbedUnimplementedOrderManagementServer() 77 | } 78 | 79 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 80 | type UnimplementedOrderManagementServer struct { 81 | } 82 | 83 | func (UnimplementedOrderManagementServer) UpdateOrders(OrderManagement_UpdateOrdersServer) error { 84 | return status.Errorf(codes.Unimplemented, "method UpdateOrders not implemented") 85 | } 86 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 87 | 88 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 89 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 90 | // result in compilation errors. 91 | type UnsafeOrderManagementServer interface { 92 | mustEmbedUnimplementedOrderManagementServer() 93 | } 94 | 95 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 96 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 97 | } 98 | 99 | func _OrderManagement_UpdateOrders_Handler(srv interface{}, stream grpc.ServerStream) error { 100 | return srv.(OrderManagementServer).UpdateOrders(&orderManagementUpdateOrdersServer{stream}) 101 | } 102 | 103 | type OrderManagement_UpdateOrdersServer interface { 104 | SendAndClose(*wrapperspb.StringValue) error 105 | Recv() (*Order, error) 106 | grpc.ServerStream 107 | } 108 | 109 | type orderManagementUpdateOrdersServer struct { 110 | grpc.ServerStream 111 | } 112 | 113 | func (x *orderManagementUpdateOrdersServer) SendAndClose(m *wrapperspb.StringValue) error { 114 | return x.ServerStream.SendMsg(m) 115 | } 116 | 117 | func (x *orderManagementUpdateOrdersServer) Recv() (*Order, error) { 118 | m := new(Order) 119 | if err := x.ServerStream.RecvMsg(m); err != nil { 120 | return nil, err 121 | } 122 | return m, nil 123 | } 124 | 125 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 126 | // It's only intended for direct use with grpc.RegisterService, 127 | // and not to be introspected or modified (even as a copy) 128 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 129 | ServiceName: "ecommerce.OrderManagement", 130 | HandlerType: (*OrderManagementServer)(nil), 131 | Methods: []grpc.MethodDesc{}, 132 | Streams: []grpc.StreamDesc{ 133 | { 134 | StreamName: "updateOrders", 135 | Handler: _OrderManagement_UpdateOrders_Handler, 136 | ClientStreams: true, 137 | }, 138 | }, 139 | Metadata: "order.proto", 140 | } 141 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/client_streaming_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.27.1 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.0 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | string destination = 5; 15 | } 16 | 17 | service OrderManagement { 18 | rpc updateOrders(stream Order) returns (google.protobuf.StringValue); 19 | } -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 13 | 14 | lit, err := net.Listen("tcp", ":8009") 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | if err := s.Serve(lit); err != nil { 20 | panic(err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /03-client_streaming_rpc_example/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 8 | "google.golang.org/protobuf/types/known/wrapperspb" 9 | ) 10 | 11 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 12 | 13 | var orders = map[string]pb.Order{ 14 | "101": { 15 | Id: "101", 16 | Items: []string{ 17 | "Google", 18 | "Baidu", 19 | }, 20 | Description: "example", 21 | Price: 0, 22 | Destination: "example", 23 | }, 24 | } 25 | 26 | type OrderManagementImpl struct { 27 | pb.UnimplementedOrderManagementServer 28 | } 29 | 30 | // 在这段程序中,我们对每一个 Recv 都进行了处理 31 | // 当发现 io.EOF (流关闭) 后,需要将最终的响应结果发送给客户端,同时关闭正在另外一侧等待的 Recv 32 | func (s *OrderManagementImpl) UpdateOrders(stream pb.OrderManagement_UpdateOrdersServer) error { 33 | ordersStr := "Updated Order IDs : " 34 | for { 35 | order, err := stream.Recv() 36 | if err == io.EOF { 37 | // Finished reading the order stream. 38 | return stream.SendAndClose( 39 | &wrapperspb.StringValue{Value: "Orders processed " + ordersStr}) 40 | } 41 | // Update order 42 | orders[order.Id] = *order 43 | 44 | log.Println("Order ID ", order.Id, ": Updated") 45 | ordersStr += order.Id + ", " 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | 8 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("127.0.0.1:8009", 15 | grpc.WithInsecure(), 16 | ) 17 | if err != nil { 18 | panic(err) 19 | } 20 | 21 | c := pb.NewOrderManagementClient(conn) 22 | ctx, cancelFn := context.WithCancel(context.Background()) 23 | defer cancelFn() 24 | 25 | stream, err := c.ProcessOrders(ctx) 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | go func() { 31 | if err := stream.Send(&wrapperspb.StringValue{Value: "101"}); err != nil { 32 | panic(err) 33 | } 34 | 35 | if err := stream.Send(&wrapperspb.StringValue{Value: "102"}); err != nil { 36 | panic(err) 37 | } 38 | 39 | if err := stream.CloseSend(); err != nil { 40 | panic(err) 41 | } 42 | }() 43 | 44 | for { 45 | combinedShipment, err := stream.Recv() 46 | if err == io.EOF { 47 | break 48 | } 49 | log.Println("Combined shipment : ", combinedShipment.OrderList) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/ecommerce/order_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | ProcessOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_ProcessOrdersClient, error) 27 | } 28 | 29 | type orderManagementClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 34 | return &orderManagementClient{cc} 35 | } 36 | 37 | func (c *orderManagementClient) ProcessOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_ProcessOrdersClient, error) { 38 | stream, err := c.cc.NewStream(ctx, &OrderManagement_ServiceDesc.Streams[0], "/ecommerce.OrderManagement/processOrders", opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | x := &orderManagementProcessOrdersClient{stream} 43 | return x, nil 44 | } 45 | 46 | type OrderManagement_ProcessOrdersClient interface { 47 | Send(*wrapperspb.StringValue) error 48 | Recv() (*CombinedShipment, error) 49 | grpc.ClientStream 50 | } 51 | 52 | type orderManagementProcessOrdersClient struct { 53 | grpc.ClientStream 54 | } 55 | 56 | func (x *orderManagementProcessOrdersClient) Send(m *wrapperspb.StringValue) error { 57 | return x.ClientStream.SendMsg(m) 58 | } 59 | 60 | func (x *orderManagementProcessOrdersClient) Recv() (*CombinedShipment, error) { 61 | m := new(CombinedShipment) 62 | if err := x.ClientStream.RecvMsg(m); err != nil { 63 | return nil, err 64 | } 65 | return m, nil 66 | } 67 | 68 | // OrderManagementServer is the server API for OrderManagement service. 69 | // All implementations must embed UnimplementedOrderManagementServer 70 | // for forward compatibility 71 | type OrderManagementServer interface { 72 | ProcessOrders(OrderManagement_ProcessOrdersServer) error 73 | mustEmbedUnimplementedOrderManagementServer() 74 | } 75 | 76 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 77 | type UnimplementedOrderManagementServer struct { 78 | } 79 | 80 | func (UnimplementedOrderManagementServer) ProcessOrders(OrderManagement_ProcessOrdersServer) error { 81 | return status.Errorf(codes.Unimplemented, "method ProcessOrders not implemented") 82 | } 83 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 84 | 85 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 86 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 87 | // result in compilation errors. 88 | type UnsafeOrderManagementServer interface { 89 | mustEmbedUnimplementedOrderManagementServer() 90 | } 91 | 92 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 93 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 94 | } 95 | 96 | func _OrderManagement_ProcessOrders_Handler(srv interface{}, stream grpc.ServerStream) error { 97 | return srv.(OrderManagementServer).ProcessOrders(&orderManagementProcessOrdersServer{stream}) 98 | } 99 | 100 | type OrderManagement_ProcessOrdersServer interface { 101 | Send(*CombinedShipment) error 102 | Recv() (*wrapperspb.StringValue, error) 103 | grpc.ServerStream 104 | } 105 | 106 | type orderManagementProcessOrdersServer struct { 107 | grpc.ServerStream 108 | } 109 | 110 | func (x *orderManagementProcessOrdersServer) Send(m *CombinedShipment) error { 111 | return x.ServerStream.SendMsg(m) 112 | } 113 | 114 | func (x *orderManagementProcessOrdersServer) Recv() (*wrapperspb.StringValue, error) { 115 | m := new(wrapperspb.StringValue) 116 | if err := x.ServerStream.RecvMsg(m); err != nil { 117 | return nil, err 118 | } 119 | return m, nil 120 | } 121 | 122 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 123 | // It's only intended for direct use with grpc.RegisterService, 124 | // and not to be introspected or modified (even as a copy) 125 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 126 | ServiceName: "ecommerce.OrderManagement", 127 | HandlerType: (*OrderManagementServer)(nil), 128 | Methods: []grpc.MethodDesc{}, 129 | Streams: []grpc.StreamDesc{ 130 | { 131 | StreamName: "processOrders", 132 | Handler: _OrderManagement_ProcessOrders_Handler, 133 | ServerStreams: true, 134 | ClientStreams: true, 135 | }, 136 | }, 137 | Metadata: "order.proto", 138 | } 139 | -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.27.1 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.0 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | string destination = 5; 15 | } 16 | 17 | message CombinedShipment { 18 | string id = 1; 19 | string status = 2; 20 | repeated Order orderList = 3; 21 | } 22 | 23 | service OrderManagement { 24 | rpc processOrders(stream google.protobuf.StringValue) 25 | returns (stream CombinedShipment); 26 | } -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | 13 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 14 | 15 | lit, err := net.Listen("tcp", ":8009") 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | if err := s.Serve(lit); err != nil { 21 | panic(err) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /04-bidirectional_streaming_rpc_example/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 8 | ) 9 | 10 | const ( 11 | orderBatchSize = 3 12 | ) 13 | 14 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 15 | 16 | var orders = map[string]pb.Order{ 17 | "101": { 18 | Id: "101", 19 | Items: []string{ 20 | "Google", 21 | "Baidu", 22 | }, 23 | Description: "example", 24 | Price: 0, 25 | Destination: "example", 26 | }, 27 | } 28 | 29 | type OrderManagementImpl struct { 30 | pb.UnimplementedOrderManagementServer 31 | } 32 | 33 | func (s *OrderManagementImpl) ProcessOrders(stream pb.OrderManagement_ProcessOrdersServer) error { 34 | 35 | batchMarker := 1 36 | var combinedShipmentMap = make(map[string]pb.CombinedShipment) 37 | for { 38 | orderId, err := stream.Recv() 39 | if err == io.EOF { 40 | for _, shipment := range combinedShipmentMap { 41 | if err := stream.Send(&shipment); err != nil { 42 | return err 43 | } 44 | } 45 | return nil 46 | } 47 | if err != nil { 48 | log.Println(err) 49 | return err 50 | } 51 | 52 | destination := orders[orderId.GetValue()].Destination 53 | shipment, found := combinedShipmentMap[destination] 54 | 55 | if found { 56 | ord := orders[orderId.GetValue()] 57 | shipment.OrderList = append(shipment.OrderList, &ord) 58 | combinedShipmentMap[destination] = shipment 59 | } else { 60 | comShip := pb.CombinedShipment{Id: "cmb - " + (orders[orderId.GetValue()].Destination), Status: "Processed!"} 61 | ord := orders[orderId.GetValue()] 62 | comShip.OrderList = append(shipment.OrderList, &ord) 63 | combinedShipmentMap[destination] = comShip 64 | log.Print(len(comShip.OrderList), comShip.GetId()) 65 | } 66 | 67 | if batchMarker == orderBatchSize { 68 | for _, comb := range combinedShipmentMap { 69 | log.Printf("Shipping : %v -> %v", comb.Id, len(comb.OrderList)) 70 | if err := stream.Send(&comb); err != nil { 71 | return err 72 | } 73 | } 74 | batchMarker = 0 75 | combinedShipmentMap = make(map[string]pb.CombinedShipment) 76 | } else { 77 | batchMarker++ 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | 8 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("127.0.0.1:8009", 15 | grpc.WithInsecure(), 16 | ) 17 | if err != nil { 18 | panic(err) 19 | } 20 | 21 | c := pb.NewOrderManagementClient(conn) 22 | ctx, cancelFn := context.WithCancel(context.Background()) 23 | defer cancelFn() 24 | 25 | // Add Order 26 | order := pb.Order{Id: "101", Items: []string{"iPhone XS", "Mac Book Pro"}, Destination: "San Jose, CA", Price: 2300.00} 27 | res, err := c.AddOrder(ctx, &order) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | log.Print("AddOrder Response -> ", res.Value) 33 | 34 | // Get Order 35 | retrievedOrder, err := c.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | log.Print("GetOrder Response -> : ", retrievedOrder) 41 | 42 | stream, err := c.ProcessOrders(ctx) 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | go func() { 48 | if err := stream.Send(&wrapperspb.StringValue{Value: "101"}); err != nil { 49 | panic(err) 50 | } 51 | 52 | if err := stream.Send(&wrapperspb.StringValue{Value: "102"}); err != nil { 53 | panic(err) 54 | } 55 | 56 | if err := stream.CloseSend(); err != nil { 57 | panic(err) 58 | } 59 | }() 60 | 61 | for { 62 | combinedShipment, err := stream.Recv() 63 | if err == io.EOF { 64 | break 65 | } 66 | log.Println("Combined shipment : ", combinedShipment.OrderList) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.27.1 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.0 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | string destination = 5; 15 | } 16 | 17 | message CombinedShipment { 18 | string id = 1; 19 | string status = 2; 20 | repeated Order orderList = 3; 21 | } 22 | 23 | service OrderManagement { 24 | rpc addOrder(Order) returns (google.protobuf.StringValue); 25 | rpc getOrder(google.protobuf.StringValue) returns (Order); 26 | rpc searchOrders(google.protobuf.StringValue) returns (stream Order); 27 | rpc updateOrders(stream Order) returns (google.protobuf.StringValue); 28 | rpc processOrders(stream google.protobuf.StringValue) 29 | returns (stream CombinedShipment); 30 | } -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | 13 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 14 | 15 | lit, err := net.Listen("tcp", ":8009") 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | if err := s.Serve(lit); err != nil { 21 | panic(err) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /05-all_in_one_rpc_example/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | "strings" 9 | 10 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/status" 13 | "google.golang.org/protobuf/types/known/wrapperspb" 14 | ) 15 | 16 | const ( 17 | orderBatchSize = 3 18 | ) 19 | 20 | var ( 21 | _ pb.OrderManagementServer = &OrderManagementImpl{} 22 | orders = make(map[string]pb.Order, 0) 23 | ) 24 | 25 | type OrderManagementImpl struct { 26 | pb.UnimplementedOrderManagementServer 27 | } 28 | 29 | // Simple RPC 30 | func (s *OrderManagementImpl) AddOrder(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 31 | log.Printf("Order Added. ID : %v", orderReq.Id) 32 | orders[orderReq.Id] = *orderReq 33 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 34 | } 35 | 36 | // Simple RPC 37 | func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 38 | ord, exists := orders[orderId.Value] 39 | if exists { 40 | return &ord, status.New(codes.OK, "").Err() 41 | } 42 | 43 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 44 | } 45 | 46 | // Server-Streaming RPC 47 | func (s *OrderManagementImpl) SearchOrders(query *wrapperspb.StringValue, stream pb.OrderManagement_SearchOrdersServer) error { 48 | for _, order := range orders { 49 | for _, str := range order.Items { 50 | if strings.Contains(str, query.Value) { 51 | err := stream.Send(&order) 52 | if err != nil { 53 | return fmt.Errorf("error send: %v", err) 54 | } 55 | } 56 | } 57 | } 58 | 59 | return nil 60 | } 61 | 62 | // Client-Streaming RPC 63 | // 在这段程序中,我们对每一个 Recv 都进行了处理 64 | // 当发现 io.EOF (流关闭) 后,需要将最终的响应结果发送给客户端,同时关闭正在另外一侧等待的 Recv 65 | func (s *OrderManagementImpl) UpdateOrders(stream pb.OrderManagement_UpdateOrdersServer) error { 66 | ordersStr := "Updated Order IDs : " 67 | for { 68 | order, err := stream.Recv() 69 | if err == io.EOF { 70 | // Finished reading the order stream. 71 | return stream.SendAndClose( 72 | &wrapperspb.StringValue{Value: "Orders processed " + ordersStr}) 73 | } 74 | // Update order 75 | orders[order.Id] = *order 76 | 77 | log.Println("Order ID ", order.Id, ": Updated") 78 | ordersStr += order.Id + ", " 79 | } 80 | } 81 | 82 | func (s *OrderManagementImpl) ProcessOrders(stream pb.OrderManagement_ProcessOrdersServer) error { 83 | 84 | batchMarker := 1 85 | var combinedShipmentMap = make(map[string]pb.CombinedShipment) 86 | for { 87 | orderId, err := stream.Recv() 88 | if err == io.EOF { 89 | for _, shipment := range combinedShipmentMap { 90 | if err := stream.Send(&shipment); err != nil { 91 | return err 92 | } 93 | } 94 | return nil 95 | } 96 | if err != nil { 97 | log.Println(err) 98 | return err 99 | } 100 | 101 | destination := orders[orderId.GetValue()].Destination 102 | shipment, found := combinedShipmentMap[destination] 103 | 104 | if found { 105 | ord := orders[orderId.GetValue()] 106 | shipment.OrderList = append(shipment.OrderList, &ord) 107 | combinedShipmentMap[destination] = shipment 108 | } else { 109 | comShip := pb.CombinedShipment{Id: "cmb - " + (orders[orderId.GetValue()].Destination), Status: "Processed!"} 110 | ord := orders[orderId.GetValue()] 111 | comShip.OrderList = append(shipment.OrderList, &ord) 112 | combinedShipmentMap[destination] = comShip 113 | log.Print(len(comShip.OrderList), comShip.GetId()) 114 | } 115 | 116 | if batchMarker == orderBatchSize { 117 | for _, comb := range combinedShipmentMap { 118 | log.Printf("Shipping : %v -> %v", comb.Id, len(comb.OrderList)) 119 | if err := stream.Send(&comb); err != nil { 120 | return err 121 | } 122 | } 123 | batchMarker = 0 124 | combinedShipmentMap = make(map[string]pb.CombinedShipment) 125 | } else { 126 | batchMarker++ 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /06-interceptors/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative -------------------------------------------------------------------------------- /06-interceptors/client/interceptor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func orderUnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, 12 | cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { 13 | // Pre-processor phase 14 | s := time.Now() 15 | 16 | // Invoking the remote method 17 | err := invoker(ctx, method, req, reply, cc, opts...) 18 | 19 | // Post-processor phase 20 | log.Printf("method: %s, req: %s, resp: %s, latency: %s\n", 21 | method, req, reply, time.Now().Sub(s)) 22 | 23 | return err 24 | } 25 | 26 | // SendMsg method call. 27 | type wrappedStream struct { 28 | method string 29 | grpc.ClientStream 30 | } 31 | 32 | func (w *wrappedStream) RecvMsg(m interface{}) error { 33 | err := w.ClientStream.RecvMsg(m) 34 | 35 | log.Printf("method: %s, res: %s\n", w.method, m) 36 | 37 | return err 38 | } 39 | 40 | func (w *wrappedStream) SendMsg(m interface{}) error { 41 | err := w.ClientStream.SendMsg(m) 42 | 43 | log.Printf("method: %s, req: %s\n", w.method, m) 44 | 45 | return err 46 | } 47 | 48 | func newWrappedStream(method string, s grpc.ClientStream) *wrappedStream { 49 | return &wrappedStream{ 50 | method, 51 | s, 52 | } 53 | } 54 | 55 | func orderStreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, 56 | cc *grpc.ClientConn, method string, streamer grpc.Streamer, 57 | opts ...grpc.CallOption) (grpc.ClientStream, error) { 58 | 59 | // Pre-processing logic 60 | s := time.Now() 61 | 62 | cs, err := streamer(ctx, desc, cc, method, opts...) 63 | 64 | // Post processing logic 65 | log.Printf("method: %s, latency: %s\n", method, time.Now().Sub(s)) 66 | 67 | return newWrappedStream(method, cs), err 68 | } 69 | -------------------------------------------------------------------------------- /06-interceptors/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func main() { 12 | conn, err := grpc.Dial("127.0.0.1:8009", 13 | grpc.WithInsecure(), 14 | grpc.WithChainUnaryInterceptor( 15 | orderUnaryClientInterceptor, 16 | ), 17 | grpc.WithChainStreamInterceptor( 18 | orderStreamClientInterceptor, 19 | ), 20 | ) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | c := pb.NewOrderManagementClient(conn) 26 | ctx, cancelFn := context.WithCancel(context.Background()) 27 | defer cancelFn() 28 | 29 | // // Add Order 30 | // order := pb.Order{Id: "101", Items: []string{"iPhone XS", "Mac Book Pro"}, Destination: "San Jose, CA", Price: 2300.00} 31 | // res, err := c.AddOrder(ctx, &order) 32 | // if err != nil { 33 | // panic(err) 34 | // } 35 | 36 | // log.Print("AddOrder Response -> ", res.Value) 37 | 38 | /////////// unary RPC ////////// 39 | 40 | // // Get Order 41 | // retrievedOrder, err := c.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 42 | // if err != nil { 43 | // panic(err) 44 | // } 45 | 46 | // log.Print("GetOrder Response -> : ", retrievedOrder) 47 | 48 | /////////// 客户端流式 RPC ////////// 49 | 50 | stream, err := c.UpdateOrders(ctx) 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | if err := stream.Send(&pb.Order{ 56 | Id: "00", 57 | Items: []string{"A", "B"}, 58 | Description: "A with B", 59 | Price: 0.11, 60 | Destination: "ABC", 61 | }); err != nil { 62 | panic(err) 63 | } 64 | 65 | if err := stream.Send(&pb.Order{ 66 | Id: "01", 67 | Items: []string{"C", "D"}, 68 | Description: "C with D", 69 | Price: 1.11, 70 | Destination: "ABCDEFG", 71 | }); err != nil { 72 | panic(err) 73 | } 74 | 75 | res, err := stream.CloseAndRecv() 76 | if err != nil { 77 | panic(err) 78 | } 79 | 80 | log.Printf("Update Orders Res : %s", res) 81 | 82 | /////////// 双向流式 RPC ////////// 83 | 84 | // stream, err := c.ProcessOrders(ctx) 85 | // if err != nil { 86 | // panic(err) 87 | // } 88 | 89 | // go func() { 90 | // if err := stream.Send(&wrapperspb.StringValue{Value: "101"}); err != nil { 91 | // panic(err) 92 | // } 93 | 94 | // if err := stream.Send(&wrapperspb.StringValue{Value: "102"}); err != nil { 95 | // panic(err) 96 | // } 97 | 98 | // if err := stream.CloseSend(); err != nil { 99 | // panic(err) 100 | // } 101 | // }() 102 | 103 | // for { 104 | // combinedShipment, err := stream.Recv() 105 | // if err == io.EOF { 106 | // break 107 | // } 108 | // log.Println("Combined shipment : ", combinedShipment.OrderList) 109 | // } 110 | } 111 | -------------------------------------------------------------------------------- /06-interceptors/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.1 7 | google.golang.org/grpc v1.44.0 8 | google.golang.org/protobuf v1.27.1 9 | ) 10 | 11 | require ( 12 | github.com/golang/protobuf v1.5.0 // indirect 13 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 14 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 15 | golang.org/x/text v0.3.0 // indirect 16 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /06-interceptors/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /06-interceptors/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | string destination = 5; 15 | } 16 | 17 | message CombinedShipment { 18 | string id = 1; 19 | string status = 2; 20 | repeated Order orderList = 3; 21 | } 22 | 23 | service OrderManagement { 24 | rpc addOrder(Order) returns (google.protobuf.StringValue); 25 | rpc getOrder(google.protobuf.StringValue) returns (Order); 26 | rpc searchOrders(google.protobuf.StringValue) returns (stream Order); 27 | rpc updateOrders(stream Order) returns (google.protobuf.StringValue); 28 | rpc processOrders(stream google.protobuf.StringValue) 29 | returns (stream CombinedShipment); 30 | } -------------------------------------------------------------------------------- /06-interceptors/server/interceptor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func orderUnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 12 | // Pre-processing logic 13 | s := time.Now() 14 | 15 | // Invoking the handler to complete the normal execution of a unary RPC. 16 | m, err := handler(ctx, req) 17 | 18 | // Post processing logic 19 | log.Printf("method: %s, req: %s, resp: %s, latency: %s\n", 20 | info.FullMethod, req, m, time.Now().Sub(s)) 21 | 22 | return m, err 23 | } 24 | 25 | // SendMsg method call. 26 | type wrappedStream struct { 27 | Recv []interface{} 28 | Send []interface{} 29 | grpc.ServerStream 30 | } 31 | 32 | func (w *wrappedStream) RecvMsg(m interface{}) error { 33 | err := w.ServerStream.RecvMsg(m) 34 | 35 | w.Recv = append(w.Recv, m) 36 | 37 | return err 38 | } 39 | 40 | func (w *wrappedStream) SendMsg(m interface{}) error { 41 | err := w.ServerStream.SendMsg(m) 42 | 43 | w.Send = append(w.Send, m) 44 | 45 | return err 46 | } 47 | 48 | func newWrappedStream(s grpc.ServerStream) *wrappedStream { 49 | return &wrappedStream{ 50 | make([]interface{}, 0), 51 | make([]interface{}, 0), 52 | s, 53 | } 54 | } 55 | 56 | func orderStreamServerInterceptor(srv interface{}, 57 | ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 58 | 59 | // Pre-processing logic 60 | s := time.Now() 61 | 62 | // Invoking the StreamHandler to complete the execution of RPC invocation 63 | nss := newWrappedStream(ss) 64 | err := handler(srv, nss) 65 | 66 | // Post processing logic 67 | log.Printf("method: %s, req: %+v, resp: %+v, latency: %s\n", 68 | info.FullMethod, nss.Recv, nss.Send, time.Now().Sub(s)) 69 | 70 | return err 71 | } 72 | -------------------------------------------------------------------------------- /06-interceptors/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer( 12 | grpc.ChainUnaryInterceptor( 13 | orderUnaryServerInterceptor, 14 | ), 15 | grpc.ChainStreamInterceptor( 16 | orderStreamServerInterceptor, 17 | ), 18 | ) 19 | 20 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 21 | 22 | lit, err := net.Listen("tcp", ":8009") 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | if err := s.Serve(lit); err != nil { 28 | panic(err) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /06-interceptors/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | "strings" 9 | 10 | pb "github.com/liangwt/note/grpc/bidirectional_streaming_rpc_example/ecommerce" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/status" 13 | "google.golang.org/protobuf/types/known/wrapperspb" 14 | ) 15 | 16 | const ( 17 | orderBatchSize = 3 18 | ) 19 | 20 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 21 | 22 | var orders = map[string]pb.Order{ 23 | "101": { 24 | Id: "101", 25 | Items: []string{ 26 | "Google", 27 | "Baidu", 28 | }, 29 | Description: "example", 30 | Price: 0, 31 | Destination: "example", 32 | }, 33 | } 34 | 35 | type OrderManagementImpl struct { 36 | pb.UnimplementedOrderManagementServer 37 | } 38 | 39 | // Simple RPC 40 | func (s *OrderManagementImpl) AddOrder(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 41 | log.Printf("Order Added. ID : %v", orderReq.Id) 42 | orders[orderReq.Id] = *orderReq 43 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 44 | } 45 | 46 | // Simple RPC 47 | func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 48 | ord, exists := orders[orderId.Value] 49 | if exists { 50 | return &ord, status.New(codes.OK, "").Err() 51 | } 52 | 53 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 54 | } 55 | 56 | // Server-Streaming RPC 57 | func (s *OrderManagementImpl) SearchOrders(query *wrapperspb.StringValue, stream pb.OrderManagement_SearchOrdersServer) error { 58 | for _, order := range orders { 59 | for _, str := range order.Items { 60 | if strings.Contains(str, query.Value) { 61 | err := stream.Send(&order) 62 | if err != nil { 63 | return fmt.Errorf("error send: %v", err) 64 | } 65 | } 66 | } 67 | } 68 | 69 | return nil 70 | } 71 | 72 | // Client-Streaming RPC 73 | // 在这段程序中,我们对每一个 Recv 都进行了处理 74 | // 当发现 io.EOF (流关闭) 后,需要将最终的响应结果发送给客户端,同时关闭正在另外一侧等待的 Recv 75 | func (s *OrderManagementImpl) UpdateOrders(stream pb.OrderManagement_UpdateOrdersServer) error { 76 | ordersStr := "Updated Order IDs : " 77 | for { 78 | order, err := stream.Recv() 79 | if err == io.EOF { 80 | // Finished reading the order stream. 81 | return stream.SendAndClose( 82 | &wrapperspb.StringValue{Value: "Orders processed " + ordersStr}) 83 | } 84 | // Update order 85 | orders[order.Id] = *order 86 | 87 | log.Println("Order ID ", order.Id, ": Updated") 88 | ordersStr += order.Id + ", " 89 | } 90 | } 91 | 92 | func (s *OrderManagementImpl) ProcessOrders(stream pb.OrderManagement_ProcessOrdersServer) error { 93 | 94 | batchMarker := 1 95 | var combinedShipmentMap = make(map[string]pb.CombinedShipment) 96 | for { 97 | orderId, err := stream.Recv() 98 | if err == io.EOF { 99 | for _, shipment := range combinedShipmentMap { 100 | if err := stream.Send(&shipment); err != nil { 101 | return err 102 | } 103 | } 104 | return nil 105 | } 106 | if err != nil { 107 | log.Println(err) 108 | return err 109 | } 110 | 111 | destination := orders[orderId.GetValue()].Destination 112 | shipment, found := combinedShipmentMap[destination] 113 | 114 | if found { 115 | ord := orders[orderId.GetValue()] 116 | shipment.OrderList = append(shipment.OrderList, &ord) 117 | combinedShipmentMap[destination] = shipment 118 | } else { 119 | comShip := pb.CombinedShipment{Id: "cmb - " + (orders[orderId.GetValue()].Destination), Status: "Processed!"} 120 | ord := orders[orderId.GetValue()] 121 | comShip.OrderList = append(shipment.OrderList, &ord) 122 | combinedShipmentMap[destination] = comShip 123 | log.Print(len(comShip.OrderList), comShip.GetId()) 124 | } 125 | 126 | if batchMarker == orderBatchSize { 127 | for _, comb := range combinedShipmentMap { 128 | log.Printf("Shipping : %v -> %v", comb.Id, len(comb.OrderList)) 129 | if err := stream.Send(&comb); err != nil { 130 | return err 131 | } 132 | } 133 | batchMarker = 0 134 | combinedShipmentMap = make(map[string]pb.CombinedShipment) 135 | } else { 136 | batchMarker++ 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /07-error_handling/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ./ 5 | opt: 6 | - paths=import 7 | - plugin: go-grpc 8 | out: ./ 9 | opt: 10 | - paths=import -------------------------------------------------------------------------------- /07-error_handling/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | pb "github.com/liangwt/note/grpc/error_handling/ecommerce" 9 | epb "google.golang.org/genproto/googleapis/rpc/errdetails" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/status" 13 | "google.golang.org/protobuf/types/known/wrapperspb" 14 | ) 15 | 16 | func main() { 17 | conn, err := grpc.Dial("127.0.0.1:8009", grpc.WithInsecure()) 18 | if err != nil { 19 | panic(err) 20 | } 21 | defer conn.Close() 22 | 23 | client := pb.NewOrderManagementClient(conn) 24 | 25 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 26 | defer cancel() 27 | 28 | // Get Order 29 | order, err := client.GetOrder(ctx, &wrapperspb.StringValue{Value: ""}) 30 | if err != nil { 31 | st, ok := status.FromError(err) 32 | if !ok { 33 | log.Println(err) 34 | return 35 | } 36 | 37 | switch st.Code() { 38 | case codes.InvalidArgument: 39 | for _, d := range st.Details() { 40 | switch info := d.(type) { 41 | case *epb.BadRequest_FieldViolation: 42 | log.Printf("Request Field Invalid: %s", info) 43 | default: 44 | log.Printf("Unexpected error type: %s", info) 45 | } 46 | } 47 | default: 48 | log.Printf("Unhandled error : %s ", st.String()) 49 | } 50 | 51 | return 52 | } 53 | 54 | log.Print("GetOrder Response -> : ", order) 55 | } 56 | -------------------------------------------------------------------------------- /07-error_handling/common/errors.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import "errors" 4 | 5 | var ParamsErr = errors.New("params is not valid") 6 | -------------------------------------------------------------------------------- /07-error_handling/ecommerce/product_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: pb/product.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) 27 | } 28 | 29 | type orderManagementClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 34 | return &orderManagementClient{cc} 35 | } 36 | 37 | func (c *orderManagementClient) GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) { 38 | out := new(Order) 39 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/getOrder", in, out, opts...) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return out, nil 44 | } 45 | 46 | // OrderManagementServer is the server API for OrderManagement service. 47 | // All implementations must embed UnimplementedOrderManagementServer 48 | // for forward compatibility 49 | type OrderManagementServer interface { 50 | GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) 51 | mustEmbedUnimplementedOrderManagementServer() 52 | } 53 | 54 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 55 | type UnimplementedOrderManagementServer struct { 56 | } 57 | 58 | func (UnimplementedOrderManagementServer) GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) { 59 | return nil, status.Errorf(codes.Unimplemented, "method GetOrder not implemented") 60 | } 61 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 62 | 63 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 64 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 65 | // result in compilation errors. 66 | type UnsafeOrderManagementServer interface { 67 | mustEmbedUnimplementedOrderManagementServer() 68 | } 69 | 70 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 71 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 72 | } 73 | 74 | func _OrderManagement_GetOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 75 | in := new(wrapperspb.StringValue) 76 | if err := dec(in); err != nil { 77 | return nil, err 78 | } 79 | if interceptor == nil { 80 | return srv.(OrderManagementServer).GetOrder(ctx, in) 81 | } 82 | info := &grpc.UnaryServerInfo{ 83 | Server: srv, 84 | FullMethod: "/ecommerce.OrderManagement/getOrder", 85 | } 86 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 87 | return srv.(OrderManagementServer).GetOrder(ctx, req.(*wrapperspb.StringValue)) 88 | } 89 | return interceptor(ctx, in, info, handler) 90 | } 91 | 92 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 93 | // It's only intended for direct use with grpc.RegisterService, 94 | // and not to be introspected or modified (even as a copy) 95 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 96 | ServiceName: "ecommerce.OrderManagement", 97 | HandlerType: (*OrderManagementServer)(nil), 98 | Methods: []grpc.MethodDesc{ 99 | { 100 | MethodName: "getOrder", 101 | Handler: _OrderManagement_GetOrder_Handler, 102 | }, 103 | }, 104 | Streams: []grpc.StreamDesc{}, 105 | Metadata: "pb/product.proto", 106 | } 107 | -------------------------------------------------------------------------------- /07-error_handling/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/error_handling 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.25.0 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.4.3 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /07-error_handling/inner/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | func Invoke2() { 13 | ok := status.New(codes.OK, "ok") 14 | fmt.Println(ok) 15 | 16 | invalidArgument := status.New(codes.InvalidArgument, "invalid args") 17 | fmt.Println(invalidArgument) 18 | } 19 | 20 | var ( 21 | ParamsErr = errors.New("params err") 22 | BizErr = errors.New("biz err") 23 | ) 24 | 25 | func Invoke(i bool) error { 26 | if i { 27 | return ParamsErr 28 | } else { 29 | return BizErr 30 | } 31 | } 32 | 33 | func main() { 34 | err := Invoke(true) 35 | 36 | if err != nil { 37 | switch { 38 | case errors.Is(err, ParamsErr): 39 | log.Println("params error") 40 | case errors.Is(err, BizErr): 41 | log.Println("biz error") 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /07-error_handling/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /07-error_handling/pb/product.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | service OrderManagement { 10 | rpc getOrder(google.protobuf.StringValue) returns (Order); 11 | } 12 | 13 | message GetOrderResp{ 14 | BizErrno errno = 1; 15 | string msg = 2; 16 | Order data = 3; 17 | } 18 | 19 | enum BizErrno { 20 | Ok = 0; 21 | ParamsErr = 1; 22 | BizErr = 2; 23 | } 24 | 25 | message Order { 26 | string id = 1; 27 | repeated string items = 2; 28 | string description = 3; 29 | float price = 4; 30 | string destination = 5; 31 | } -------------------------------------------------------------------------------- /07-error_handling/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/error_handling/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | 13 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 14 | 15 | lis, err := net.Listen("tcp", ":8009") 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | if err := s.Serve(lis); err != nil { 21 | panic(err) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /07-error_handling/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | pb "github.com/liangwt/note/grpc/error_handling/ecommerce" 8 | epb "google.golang.org/genproto/googleapis/rpc/errdetails" 9 | "google.golang.org/grpc/codes" 10 | "google.golang.org/grpc/status" 11 | "google.golang.org/protobuf/types/known/wrapperspb" 12 | ) 13 | 14 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 15 | 16 | var orders = map[string]pb.Order{ 17 | "101": { 18 | Id: "101", 19 | Items: []string{ 20 | "Google", 21 | "Baidu", 22 | }, 23 | Description: "example", 24 | Price: 0, 25 | Destination: "example", 26 | }, 27 | } 28 | 29 | type OrderManagementImpl struct { 30 | pb.UnimplementedOrderManagementServer 31 | } 32 | 33 | // Simple RPC 34 | func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 35 | ord, exists := orders[orderId.Value] 36 | if exists { 37 | return &ord, status.New(codes.OK, "ok").Err() 38 | } 39 | 40 | st := status.New(codes.InvalidArgument, 41 | "Order does not exist. order id: "+orderId.Value) 42 | 43 | details, err := st.WithDetails( 44 | &epb.BadRequest_FieldViolation{ 45 | Field: "ID", 46 | Description: fmt.Sprintf("Order ID received is not valid"), 47 | }, 48 | ) 49 | if err == nil { 50 | return nil, details.Err() 51 | } 52 | 53 | return nil, st.Err() 54 | } 55 | -------------------------------------------------------------------------------- /08-metadata/client/interceptor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "strconv" 7 | "time" 8 | 9 | "google.golang.org/grpc" 10 | "google.golang.org/grpc/metadata" 11 | ) 12 | 13 | func orderUnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, 14 | cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { 15 | 16 | var s string 17 | 18 | // 获取要发送给服务端的`metadata` 19 | md, ok := metadata.FromOutgoingContext(ctx) 20 | if ok && len(md.Get("time")) > 0 { 21 | s = md.Get("time")[0] 22 | } else { 23 | // 如果没有则补充这个时间戳字段 24 | s = "inter" + strconv.FormatInt(time.Now().UnixNano(), 10) 25 | ctx = metadata.AppendToOutgoingContext(ctx, "time", s) 26 | } 27 | 28 | log.Printf("call timestamp: %s", s) 29 | 30 | // Invoking the remote method 31 | err := invoker(ctx, method, req, reply, cc, opts...) 32 | 33 | return err 34 | } 35 | 36 | // SendMsg method call. 37 | type wrappedStream struct { 38 | method string 39 | grpc.ClientStream 40 | } 41 | 42 | func (w *wrappedStream) RecvMsg(m interface{}) error { 43 | err := w.ClientStream.RecvMsg(m) 44 | 45 | log.Printf("method: %s, res: %s\n", w.method, m) 46 | 47 | return err 48 | } 49 | 50 | func (w *wrappedStream) SendMsg(m interface{}) error { 51 | err := w.ClientStream.SendMsg(m) 52 | 53 | log.Printf("method: %s, req: %s\n", w.method, m) 54 | 55 | return err 56 | } 57 | 58 | func newWrappedStream(method string, s grpc.ClientStream) *wrappedStream { 59 | return &wrappedStream{ 60 | method, 61 | s, 62 | } 63 | } 64 | 65 | func orderStreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, 66 | cc *grpc.ClientConn, method string, streamer grpc.Streamer, 67 | opts ...grpc.CallOption) (grpc.ClientStream, error) { 68 | 69 | // Pre-processing logic 70 | s := time.Now() 71 | 72 | cs, err := streamer(ctx, desc, cc, method, opts...) 73 | 74 | // Post processing logic 75 | log.Printf("method: %s, latency: %s\n", method, time.Now().Sub(s)) 76 | 77 | return newWrappedStream(method, cs), err 78 | } 79 | -------------------------------------------------------------------------------- /08-metadata/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "strconv" 7 | "time" 8 | 9 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/metadata" 12 | ) 13 | 14 | func main() { 15 | conn, err := grpc.Dial("127.0.0.1:8009", 16 | grpc.WithInsecure(), 17 | grpc.WithChainUnaryInterceptor( 18 | orderUnaryClientInterceptor, 19 | ), 20 | ) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | c := pb.NewOrderManagementClient(conn) 26 | 27 | ctx, cancelFn := context.WithCancel(context.Background()) 28 | defer cancelFn() 29 | 30 | ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("k1", "v1", "k2", "v2")) 31 | ctx = metadata.AppendToOutgoingContext(ctx, "time", 32 | "raw"+strconv.FormatInt(time.Now().UnixNano(), 10)) 33 | 34 | // RPC using the context with new metadata. 35 | var header, trailer metadata.MD 36 | 37 | // Add Order 38 | order := pb.Order{ 39 | Id: "101", 40 | Items: []string{"iPhone XS", "Mac Book Pro"}, 41 | Destination: "San Jose, CA", 42 | Price: 2300.00, 43 | } 44 | res, err := c.AddOrder(ctx, &order, grpc.Header(&header), grpc.Trailer(&trailer)) 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | log.Printf("#AddOrder## header: %v. trailer: %v", header, trailer) 50 | 51 | ////////// 52 | 53 | stream, err := c.UpdateOrders(ctx) 54 | if err != nil { 55 | panic(err) 56 | } 57 | // retrieve header 58 | header, _ = stream.Header() 59 | // retrieve trailer 60 | trailer = stream.Trailer() 61 | 62 | if err := stream.Send(&pb.Order{ 63 | Id: "00", 64 | Items: []string{"A", "B"}, 65 | Description: "A with B", 66 | Price: 0.11, 67 | Destination: "ABC", 68 | }); err != nil { 69 | panic(err) 70 | } 71 | 72 | if err := stream.Send(&pb.Order{ 73 | Id: "01", 74 | Items: []string{"C", "D"}, 75 | Description: "C with D", 76 | Price: 1.11, 77 | Destination: "ABCDEFG", 78 | }); err != nil { 79 | panic(err) 80 | } 81 | 82 | res, err = stream.CloseAndRecv() 83 | if err != nil { 84 | panic(err) 85 | } 86 | 87 | // retrieve trailer 88 | trailer = stream.Trailer() 89 | 90 | log.Printf("##UpdateOrders## header: %v. trailer: %v", header, trailer) 91 | 92 | log.Printf("Update Orders Res : %s", res) 93 | } 94 | -------------------------------------------------------------------------------- /08-metadata/ecommerce/order_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.3 5 | // source: pb/order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) 27 | UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) 28 | } 29 | 30 | type orderManagementClient struct { 31 | cc grpc.ClientConnInterface 32 | } 33 | 34 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 35 | return &orderManagementClient{cc} 36 | } 37 | 38 | func (c *orderManagementClient) AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { 39 | out := new(wrapperspb.StringValue) 40 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/addOrder", in, out, opts...) 41 | if err != nil { 42 | return nil, err 43 | } 44 | return out, nil 45 | } 46 | 47 | func (c *orderManagementClient) UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) { 48 | stream, err := c.cc.NewStream(ctx, &OrderManagement_ServiceDesc.Streams[0], "/ecommerce.OrderManagement/updateOrders", opts...) 49 | if err != nil { 50 | return nil, err 51 | } 52 | x := &orderManagementUpdateOrdersClient{stream} 53 | return x, nil 54 | } 55 | 56 | type OrderManagement_UpdateOrdersClient interface { 57 | Send(*Order) error 58 | CloseAndRecv() (*wrapperspb.StringValue, error) 59 | grpc.ClientStream 60 | } 61 | 62 | type orderManagementUpdateOrdersClient struct { 63 | grpc.ClientStream 64 | } 65 | 66 | func (x *orderManagementUpdateOrdersClient) Send(m *Order) error { 67 | return x.ClientStream.SendMsg(m) 68 | } 69 | 70 | func (x *orderManagementUpdateOrdersClient) CloseAndRecv() (*wrapperspb.StringValue, error) { 71 | if err := x.ClientStream.CloseSend(); err != nil { 72 | return nil, err 73 | } 74 | m := new(wrapperspb.StringValue) 75 | if err := x.ClientStream.RecvMsg(m); err != nil { 76 | return nil, err 77 | } 78 | return m, nil 79 | } 80 | 81 | // OrderManagementServer is the server API for OrderManagement service. 82 | // All implementations must embed UnimplementedOrderManagementServer 83 | // for forward compatibility 84 | type OrderManagementServer interface { 85 | AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) 86 | UpdateOrders(OrderManagement_UpdateOrdersServer) error 87 | mustEmbedUnimplementedOrderManagementServer() 88 | } 89 | 90 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 91 | type UnimplementedOrderManagementServer struct { 92 | } 93 | 94 | func (UnimplementedOrderManagementServer) AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) { 95 | return nil, status.Errorf(codes.Unimplemented, "method AddOrder not implemented") 96 | } 97 | func (UnimplementedOrderManagementServer) UpdateOrders(OrderManagement_UpdateOrdersServer) error { 98 | return status.Errorf(codes.Unimplemented, "method UpdateOrders not implemented") 99 | } 100 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 101 | 102 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 103 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 104 | // result in compilation errors. 105 | type UnsafeOrderManagementServer interface { 106 | mustEmbedUnimplementedOrderManagementServer() 107 | } 108 | 109 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 110 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 111 | } 112 | 113 | func _OrderManagement_AddOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 114 | in := new(Order) 115 | if err := dec(in); err != nil { 116 | return nil, err 117 | } 118 | if interceptor == nil { 119 | return srv.(OrderManagementServer).AddOrder(ctx, in) 120 | } 121 | info := &grpc.UnaryServerInfo{ 122 | Server: srv, 123 | FullMethod: "/ecommerce.OrderManagement/addOrder", 124 | } 125 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 126 | return srv.(OrderManagementServer).AddOrder(ctx, req.(*Order)) 127 | } 128 | return interceptor(ctx, in, info, handler) 129 | } 130 | 131 | func _OrderManagement_UpdateOrders_Handler(srv interface{}, stream grpc.ServerStream) error { 132 | return srv.(OrderManagementServer).UpdateOrders(&orderManagementUpdateOrdersServer{stream}) 133 | } 134 | 135 | type OrderManagement_UpdateOrdersServer interface { 136 | SendAndClose(*wrapperspb.StringValue) error 137 | Recv() (*Order, error) 138 | grpc.ServerStream 139 | } 140 | 141 | type orderManagementUpdateOrdersServer struct { 142 | grpc.ServerStream 143 | } 144 | 145 | func (x *orderManagementUpdateOrdersServer) SendAndClose(m *wrapperspb.StringValue) error { 146 | return x.ServerStream.SendMsg(m) 147 | } 148 | 149 | func (x *orderManagementUpdateOrdersServer) Recv() (*Order, error) { 150 | m := new(Order) 151 | if err := x.ServerStream.RecvMsg(m); err != nil { 152 | return nil, err 153 | } 154 | return m, nil 155 | } 156 | 157 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 158 | // It's only intended for direct use with grpc.RegisterService, 159 | // and not to be introspected or modified (even as a copy) 160 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 161 | ServiceName: "ecommerce.OrderManagement", 162 | HandlerType: (*OrderManagementServer)(nil), 163 | Methods: []grpc.MethodDesc{ 164 | { 165 | MethodName: "addOrder", 166 | Handler: _OrderManagement_AddOrder_Handler, 167 | }, 168 | }, 169 | Streams: []grpc.StreamDesc{ 170 | { 171 | StreamName: "updateOrders", 172 | Handler: _OrderManagement_UpdateOrders_Handler, 173 | ClientStreams: true, 174 | }, 175 | }, 176 | Metadata: "pb/order.proto", 177 | } 178 | -------------------------------------------------------------------------------- /08-metadata/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/client_streaming_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.27.1 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.0 // indirect 12 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 13 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 14 | golang.org/x/text v0.3.0 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /08-metadata/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | google.protobuf.StringValue destination = 5; 15 | } 16 | 17 | service OrderManagement { 18 | rpc addOrder(Order) returns (google.protobuf.StringValue); 19 | rpc updateOrders(stream Order) returns (google.protobuf.StringValue); 20 | } -------------------------------------------------------------------------------- /08-metadata/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | pb.RegisterOrderManagementServer(s, &server{}) 13 | 14 | lit, err := net.Listen("tcp", ":8009") 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | if err := s.Serve(lit); err != nil { 20 | panic(err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /08-metadata/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | 8 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/grpc/metadata" 11 | "google.golang.org/protobuf/types/known/wrapperspb" 12 | ) 13 | 14 | var _ pb.OrderManagementServer = &server{} 15 | 16 | var orders = make(map[string]pb.Order, 0) 17 | 18 | type server struct { 19 | pb.UnimplementedOrderManagementServer 20 | } 21 | 22 | // Simple RPC 23 | func (s *server) AddOrder(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 24 | log.Printf("Order Added. ID : %v", orderReq.Id) 25 | 26 | md, ok := metadata.FromIncomingContext(ctx) 27 | log.Printf("has: %t. md: %v", ok, md) 28 | 29 | orders[orderReq.Id] = *orderReq 30 | 31 | grpc.SetHeader(ctx, metadata.Pairs("header-key1", "val1")) 32 | 33 | // create and send header 34 | header := metadata.Pairs("header-key", "val") 35 | grpc.SendHeader(ctx, header) 36 | 37 | // create and set trailer 38 | trailer := metadata.Pairs("trailer-key", "val") 39 | grpc.SetTrailer(ctx, trailer) 40 | 41 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 42 | } 43 | 44 | // 在这段程序中,我们对每一个 Recv 都进行了处理 45 | // 当发现 io.EOF (流关闭) 后,需要将最终的响应结果发送给客户端,同时关闭正在另外一侧等待的 Recv 46 | func (s *server) UpdateOrders(stream pb.OrderManagement_UpdateOrdersServer) error { 47 | md, ok := metadata.FromIncomingContext(stream.Context()) 48 | log.Printf("has: %t. md: %v", ok, md) 49 | 50 | // create and send header 51 | header := metadata.Pairs("header-key", "val") 52 | stream.SetHeader(header) 53 | 54 | 55 | // create and set trailer 56 | trailer := metadata.Pairs("trailer-key", "val") 57 | stream.SetTrailer(trailer) 58 | 59 | ordersStr := "Updated Order IDs : " 60 | for { 61 | order, err := stream.Recv() 62 | if err == io.EOF { 63 | // Finished reading the order stream. 64 | return stream.SendAndClose( 65 | &wrapperspb.StringValue{Value: "Orders processed " + ordersStr}) 66 | } 67 | 68 | // Update order 69 | orders[order.Id] = *order 70 | 71 | log.Println("Order ID ", order.Id, ": Updated") 72 | ordersStr += order.Id + ", " 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /09-timeout/client/interceptor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func unaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, 11 | cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { 12 | 13 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 14 | defer cancel() 15 | 16 | // Invoking the remote method 17 | err := invoker(ctx, method, req, reply, cc, opts...) 18 | 19 | return err 20 | } 21 | -------------------------------------------------------------------------------- /09-timeout/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/grpc/codes" 11 | "google.golang.org/grpc/status" 12 | ) 13 | 14 | func main() { 15 | ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second) 16 | defer cancel() 17 | 18 | conn, err := grpc.DialContext(ctx, "127.0.0.1:8009", 19 | grpc.WithInsecure(), 20 | grpc.WithBlock(), 21 | grpc.WithUnaryInterceptor(unaryClientInterceptor), 22 | ) 23 | if err != nil { 24 | if err == context.DeadlineExceeded { 25 | panic(err) 26 | } 27 | panic(err) 28 | } 29 | 30 | c := pb.NewOrderManagementClient(conn) 31 | 32 | ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second) 33 | defer cancel() 34 | 35 | // Add Order 36 | order := pb.Order{ 37 | Id: "101", 38 | Items: []string{"iPhone XS", "Mac Book Pro"}, 39 | Destination: "San Jose, CA", 40 | Price: 2300.00, 41 | } 42 | res, err := c.AddOrder(ctx, &order) 43 | if err != nil { 44 | st, ok := status.FromError(err) 45 | if ok && st.Code() == codes.DeadlineExceeded { 46 | panic(err) 47 | } 48 | panic(err) 49 | } 50 | 51 | log.Println(res) 52 | } 53 | -------------------------------------------------------------------------------- /09-timeout/ecommerce/order_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.3 5 | // source: pb/order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) 27 | UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) 28 | } 29 | 30 | type orderManagementClient struct { 31 | cc grpc.ClientConnInterface 32 | } 33 | 34 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 35 | return &orderManagementClient{cc} 36 | } 37 | 38 | func (c *orderManagementClient) AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { 39 | out := new(wrapperspb.StringValue) 40 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/addOrder", in, out, opts...) 41 | if err != nil { 42 | return nil, err 43 | } 44 | return out, nil 45 | } 46 | 47 | func (c *orderManagementClient) UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) { 48 | stream, err := c.cc.NewStream(ctx, &OrderManagement_ServiceDesc.Streams[0], "/ecommerce.OrderManagement/updateOrders", opts...) 49 | if err != nil { 50 | return nil, err 51 | } 52 | x := &orderManagementUpdateOrdersClient{stream} 53 | return x, nil 54 | } 55 | 56 | type OrderManagement_UpdateOrdersClient interface { 57 | Send(*Order) error 58 | CloseAndRecv() (*wrapperspb.StringValue, error) 59 | grpc.ClientStream 60 | } 61 | 62 | type orderManagementUpdateOrdersClient struct { 63 | grpc.ClientStream 64 | } 65 | 66 | func (x *orderManagementUpdateOrdersClient) Send(m *Order) error { 67 | return x.ClientStream.SendMsg(m) 68 | } 69 | 70 | func (x *orderManagementUpdateOrdersClient) CloseAndRecv() (*wrapperspb.StringValue, error) { 71 | if err := x.ClientStream.CloseSend(); err != nil { 72 | return nil, err 73 | } 74 | m := new(wrapperspb.StringValue) 75 | if err := x.ClientStream.RecvMsg(m); err != nil { 76 | return nil, err 77 | } 78 | return m, nil 79 | } 80 | 81 | // OrderManagementServer is the server API for OrderManagement service. 82 | // All implementations must embed UnimplementedOrderManagementServer 83 | // for forward compatibility 84 | type OrderManagementServer interface { 85 | AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) 86 | UpdateOrders(OrderManagement_UpdateOrdersServer) error 87 | mustEmbedUnimplementedOrderManagementServer() 88 | } 89 | 90 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 91 | type UnimplementedOrderManagementServer struct { 92 | } 93 | 94 | func (UnimplementedOrderManagementServer) AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) { 95 | return nil, status.Errorf(codes.Unimplemented, "method AddOrder not implemented") 96 | } 97 | func (UnimplementedOrderManagementServer) UpdateOrders(OrderManagement_UpdateOrdersServer) error { 98 | return status.Errorf(codes.Unimplemented, "method UpdateOrders not implemented") 99 | } 100 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 101 | 102 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 103 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 104 | // result in compilation errors. 105 | type UnsafeOrderManagementServer interface { 106 | mustEmbedUnimplementedOrderManagementServer() 107 | } 108 | 109 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 110 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 111 | } 112 | 113 | func _OrderManagement_AddOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 114 | in := new(Order) 115 | if err := dec(in); err != nil { 116 | return nil, err 117 | } 118 | if interceptor == nil { 119 | return srv.(OrderManagementServer).AddOrder(ctx, in) 120 | } 121 | info := &grpc.UnaryServerInfo{ 122 | Server: srv, 123 | FullMethod: "/ecommerce.OrderManagement/addOrder", 124 | } 125 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 126 | return srv.(OrderManagementServer).AddOrder(ctx, req.(*Order)) 127 | } 128 | return interceptor(ctx, in, info, handler) 129 | } 130 | 131 | func _OrderManagement_UpdateOrders_Handler(srv interface{}, stream grpc.ServerStream) error { 132 | return srv.(OrderManagementServer).UpdateOrders(&orderManagementUpdateOrdersServer{stream}) 133 | } 134 | 135 | type OrderManagement_UpdateOrdersServer interface { 136 | SendAndClose(*wrapperspb.StringValue) error 137 | Recv() (*Order, error) 138 | grpc.ServerStream 139 | } 140 | 141 | type orderManagementUpdateOrdersServer struct { 142 | grpc.ServerStream 143 | } 144 | 145 | func (x *orderManagementUpdateOrdersServer) SendAndClose(m *wrapperspb.StringValue) error { 146 | return x.ServerStream.SendMsg(m) 147 | } 148 | 149 | func (x *orderManagementUpdateOrdersServer) Recv() (*Order, error) { 150 | m := new(Order) 151 | if err := x.ServerStream.RecvMsg(m); err != nil { 152 | return nil, err 153 | } 154 | return m, nil 155 | } 156 | 157 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 158 | // It's only intended for direct use with grpc.RegisterService, 159 | // and not to be introspected or modified (even as a copy) 160 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 161 | ServiceName: "ecommerce.OrderManagement", 162 | HandlerType: (*OrderManagementServer)(nil), 163 | Methods: []grpc.MethodDesc{ 164 | { 165 | MethodName: "addOrder", 166 | Handler: _OrderManagement_AddOrder_Handler, 167 | }, 168 | }, 169 | Streams: []grpc.StreamDesc{ 170 | { 171 | StreamName: "updateOrders", 172 | Handler: _OrderManagement_UpdateOrders_Handler, 173 | ClientStreams: true, 174 | }, 175 | }, 176 | Metadata: "pb/order.proto", 177 | } 178 | -------------------------------------------------------------------------------- /09-timeout/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/client_streaming_rpc_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.0 7 | google.golang.org/grpc v1.44.0 8 | google.golang.org/protobuf v1.27.1 9 | ) 10 | 11 | require ( 12 | github.com/golang/protobuf v1.5.0 // indirect 13 | github.com/jinzhu/inflection v1.0.0 // indirect 14 | github.com/jinzhu/now v1.1.5 // indirect 15 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 16 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 17 | golang.org/x/text v0.3.0 // indirect 18 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 19 | gorm.io/gorm v1.24.5 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /09-timeout/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | google.protobuf.StringValue destination = 5; 15 | } 16 | 17 | service OrderManagement { 18 | rpc addOrder(Order) returns (google.protobuf.StringValue); 19 | rpc updateOrders(stream Order) returns (google.protobuf.StringValue); 20 | } -------------------------------------------------------------------------------- /09-timeout/server/interceptor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func unaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 11 | ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 12 | defer cancel() 13 | 14 | // Invoking the handler to complete the normal execution of a unary RPC. 15 | m, err := handler(ctx, req) 16 | 17 | return m, err 18 | } 19 | -------------------------------------------------------------------------------- /09-timeout/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | "time" 6 | 7 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func main() { 12 | s := grpc.NewServer( 13 | grpc.ConnectionTimeout(3*time.Second), 14 | grpc.UnaryInterceptor(unaryServerInterceptor), 15 | ) 16 | pb.RegisterOrderManagementServer(s, &server{}) 17 | 18 | lit, err := net.Listen("tcp", ":8009") 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | if err := s.Serve(lit); err != nil { 24 | panic(err) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /09-timeout/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/client_streaming_rpc_example/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &server{} 14 | 15 | var orders = make(map[string]pb.Order, 0) 16 | 17 | type server struct { 18 | pb.UnimplementedOrderManagementServer 19 | } 20 | 21 | // Simple RPC 22 | func (s *server) AddOrder(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 23 | log.Printf("Order Added. ID : %v", orderReq.Id) 24 | 25 | select { 26 | case <-ctx.Done(): 27 | return nil, status.Errorf(codes.Canceled, "Client cancelled, abandoning.") 28 | default: 29 | } 30 | 31 | orders[orderReq.Id] = *orderReq 32 | 33 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 34 | } 35 | -------------------------------------------------------------------------------- /10-secure/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "io/ioutil" 8 | "log" 9 | "time" 10 | 11 | pb "github.com/liangwt/note/grpc/secure/ecommerce" 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/credentials" 14 | "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | func main() { 18 | // 加载客户端证书 19 | certificate, err := tls.LoadX509KeyPair("x509/client.crt", "x509/client.key") 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | 24 | // 构建CertPool以校验服务端证书有效性 25 | b, err := ioutil.ReadFile("./x509/rootCa.crt") 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | cp := x509.NewCertPool() 30 | if !cp.AppendCertsFromPEM(b) { 31 | log.Fatal("credentials: failed to append certificates") 32 | } 33 | 34 | creds := credentials.NewTLS(&tls.Config{ 35 | Certificates: []tls.Certificate{certificate}, 36 | ServerName: "www.example.com", 37 | RootCAs: cp, 38 | }) 39 | 40 | conn, err := grpc.Dial("localhost:8009", grpc.WithTransportCredentials(creds)) 41 | if err != nil { 42 | panic(err) 43 | } 44 | defer conn.Close() 45 | 46 | client := pb.NewOrderManagementClient(conn) 47 | 48 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 49 | defer cancel() 50 | 51 | // Get Order 52 | retrievedOrder, err := client.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 53 | if err != nil { 54 | panic(err) 55 | } 56 | 57 | log.Print("GetOrder Response -> : ", retrievedOrder) 58 | } 59 | -------------------------------------------------------------------------------- /10-secure/ecommerce/product.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc v3.19.4 5 | // source: pb/product.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Order struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` 30 | Items []string `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` 31 | Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` 32 | Price float32 `protobuf:"fixed32,4,opt,name=price,proto3" json:"price,omitempty"` 33 | Destination string `protobuf:"bytes,5,opt,name=destination,proto3" json:"destination,omitempty"` 34 | } 35 | 36 | func (x *Order) Reset() { 37 | *x = Order{} 38 | if protoimpl.UnsafeEnabled { 39 | mi := &file_pb_product_proto_msgTypes[0] 40 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 41 | ms.StoreMessageInfo(mi) 42 | } 43 | } 44 | 45 | func (x *Order) String() string { 46 | return protoimpl.X.MessageStringOf(x) 47 | } 48 | 49 | func (*Order) ProtoMessage() {} 50 | 51 | func (x *Order) ProtoReflect() protoreflect.Message { 52 | mi := &file_pb_product_proto_msgTypes[0] 53 | if protoimpl.UnsafeEnabled && x != nil { 54 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 55 | if ms.LoadMessageInfo() == nil { 56 | ms.StoreMessageInfo(mi) 57 | } 58 | return ms 59 | } 60 | return mi.MessageOf(x) 61 | } 62 | 63 | // Deprecated: Use Order.ProtoReflect.Descriptor instead. 64 | func (*Order) Descriptor() ([]byte, []int) { 65 | return file_pb_product_proto_rawDescGZIP(), []int{0} 66 | } 67 | 68 | func (x *Order) GetId() string { 69 | if x != nil { 70 | return x.Id 71 | } 72 | return "" 73 | } 74 | 75 | func (x *Order) GetItems() []string { 76 | if x != nil { 77 | return x.Items 78 | } 79 | return nil 80 | } 81 | 82 | func (x *Order) GetDescription() string { 83 | if x != nil { 84 | return x.Description 85 | } 86 | return "" 87 | } 88 | 89 | func (x *Order) GetPrice() float32 { 90 | if x != nil { 91 | return x.Price 92 | } 93 | return 0 94 | } 95 | 96 | func (x *Order) GetDestination() string { 97 | if x != nil { 98 | return x.Destination 99 | } 100 | return "" 101 | } 102 | 103 | var File_pb_product_proto protoreflect.FileDescriptor 104 | 105 | var file_pb_product_proto_rawDesc = []byte{ 106 | 0x0a, 0x10, 0x70, 0x62, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 107 | 0x74, 0x6f, 0x12, 0x09, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x1a, 0x1e, 0x67, 108 | 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 109 | 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 110 | 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 111 | 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 112 | 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x20, 0x0a, 113 | 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 114 | 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 115 | 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 116 | 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 117 | 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 118 | 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x4d, 0x0a, 0x0f, 0x4f, 0x72, 0x64, 0x65, 0x72, 119 | 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x08, 0x67, 0x65, 120 | 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 121 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 122 | 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x10, 0x2e, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 123 | 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x0c, 0x5a, 0x0a, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 124 | 0x72, 0x63, 0x65, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 125 | } 126 | 127 | var ( 128 | file_pb_product_proto_rawDescOnce sync.Once 129 | file_pb_product_proto_rawDescData = file_pb_product_proto_rawDesc 130 | ) 131 | 132 | func file_pb_product_proto_rawDescGZIP() []byte { 133 | file_pb_product_proto_rawDescOnce.Do(func() { 134 | file_pb_product_proto_rawDescData = protoimpl.X.CompressGZIP(file_pb_product_proto_rawDescData) 135 | }) 136 | return file_pb_product_proto_rawDescData 137 | } 138 | 139 | var file_pb_product_proto_msgTypes = make([]protoimpl.MessageInfo, 1) 140 | var file_pb_product_proto_goTypes = []interface{}{ 141 | (*Order)(nil), // 0: ecommerce.Order 142 | (*wrapperspb.StringValue)(nil), // 1: google.protobuf.StringValue 143 | } 144 | var file_pb_product_proto_depIdxs = []int32{ 145 | 1, // 0: ecommerce.OrderManagement.getOrder:input_type -> google.protobuf.StringValue 146 | 0, // 1: ecommerce.OrderManagement.getOrder:output_type -> ecommerce.Order 147 | 1, // [1:2] is the sub-list for method output_type 148 | 0, // [0:1] is the sub-list for method input_type 149 | 0, // [0:0] is the sub-list for extension type_name 150 | 0, // [0:0] is the sub-list for extension extendee 151 | 0, // [0:0] is the sub-list for field type_name 152 | } 153 | 154 | func init() { file_pb_product_proto_init() } 155 | func file_pb_product_proto_init() { 156 | if File_pb_product_proto != nil { 157 | return 158 | } 159 | if !protoimpl.UnsafeEnabled { 160 | file_pb_product_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 161 | switch v := v.(*Order); i { 162 | case 0: 163 | return &v.state 164 | case 1: 165 | return &v.sizeCache 166 | case 2: 167 | return &v.unknownFields 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | type x struct{} 174 | out := protoimpl.TypeBuilder{ 175 | File: protoimpl.DescBuilder{ 176 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 177 | RawDescriptor: file_pb_product_proto_rawDesc, 178 | NumEnums: 0, 179 | NumMessages: 1, 180 | NumExtensions: 0, 181 | NumServices: 1, 182 | }, 183 | GoTypes: file_pb_product_proto_goTypes, 184 | DependencyIndexes: file_pb_product_proto_depIdxs, 185 | MessageInfos: file_pb_product_proto_msgTypes, 186 | }.Build() 187 | File_pb_product_proto = out.File 188 | file_pb_product_proto_rawDesc = nil 189 | file_pb_product_proto_goTypes = nil 190 | file_pb_product_proto_depIdxs = nil 191 | } 192 | -------------------------------------------------------------------------------- /10-secure/ecommerce/product_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.4 5 | // source: pb/product.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) 27 | } 28 | 29 | type orderManagementClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 34 | return &orderManagementClient{cc} 35 | } 36 | 37 | func (c *orderManagementClient) GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) { 38 | out := new(Order) 39 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/getOrder", in, out, opts...) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return out, nil 44 | } 45 | 46 | // OrderManagementServer is the server API for OrderManagement service. 47 | // All implementations must embed UnimplementedOrderManagementServer 48 | // for forward compatibility 49 | type OrderManagementServer interface { 50 | GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) 51 | mustEmbedUnimplementedOrderManagementServer() 52 | } 53 | 54 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 55 | type UnimplementedOrderManagementServer struct { 56 | } 57 | 58 | func (UnimplementedOrderManagementServer) GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) { 59 | return nil, status.Errorf(codes.Unimplemented, "method GetOrder not implemented") 60 | } 61 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 62 | 63 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 64 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 65 | // result in compilation errors. 66 | type UnsafeOrderManagementServer interface { 67 | mustEmbedUnimplementedOrderManagementServer() 68 | } 69 | 70 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 71 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 72 | } 73 | 74 | func _OrderManagement_GetOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 75 | in := new(wrapperspb.StringValue) 76 | if err := dec(in); err != nil { 77 | return nil, err 78 | } 79 | if interceptor == nil { 80 | return srv.(OrderManagementServer).GetOrder(ctx, in) 81 | } 82 | info := &grpc.UnaryServerInfo{ 83 | Server: srv, 84 | FullMethod: "/ecommerce.OrderManagement/getOrder", 85 | } 86 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 87 | return srv.(OrderManagementServer).GetOrder(ctx, req.(*wrapperspb.StringValue)) 88 | } 89 | return interceptor(ctx, in, info, handler) 90 | } 91 | 92 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 93 | // It's only intended for direct use with grpc.RegisterService, 94 | // and not to be introspected or modified (even as a copy) 95 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 96 | ServiceName: "ecommerce.OrderManagement", 97 | HandlerType: (*OrderManagementServer)(nil), 98 | Methods: []grpc.MethodDesc{ 99 | { 100 | MethodName: "getOrder", 101 | Handler: _OrderManagement_GetOrder_Handler, 102 | }, 103 | }, 104 | Streams: []grpc.StreamDesc{}, 105 | Metadata: "pb/product.proto", 106 | } 107 | -------------------------------------------------------------------------------- /10-secure/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/secure 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.49.0 7 | google.golang.org/protobuf v1.28.1 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.2 // indirect 12 | golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect 13 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect 14 | golang.org/x/text v0.3.3 // indirect 15 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /10-secure/pb/product.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | service OrderManagement { 10 | rpc getOrder(google.protobuf.StringValue) returns (Order); 11 | } 12 | 13 | message Order { 14 | string id = 1; 15 | repeated string items = 2; 16 | string description = 3; 17 | float price = 4; 18 | string destination = 5; 19 | } -------------------------------------------------------------------------------- /10-secure/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // "crypto/tls" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "io/ioutil" 8 | "log" 9 | "net" 10 | 11 | pb "github.com/liangwt/note/grpc/secure/ecommerce" 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/credentials" 14 | ) 15 | 16 | func main() { 17 | l, err := net.Listen("tcp", ":8009") 18 | if err != nil { 19 | panic(err) 20 | } 21 | 22 | certificate, err := tls.LoadX509KeyPair("./x509/server.crt", "./x509/server.key") 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | // 创建CertPool,后续就用池里的证书来校验客户端证书有效性 28 | // 所以如果有多个客户端 可以给每个客户端使用不同的 CA 证书,来实现分别校验的目的 29 | certPool := x509.NewCertPool() 30 | ca, err := ioutil.ReadFile("./x509/rootCa.crt") 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | if ok := certPool.AppendCertsFromPEM(ca); !ok { 35 | log.Fatal("failed to append certs") 36 | } 37 | 38 | // 构建基于 TLS 的 TransportCredentials 39 | creds := credentials.NewTLS(&tls.Config{ 40 | // 设置证书链,允许包含一个或多个 41 | Certificates: []tls.Certificate{certificate}, 42 | // 要求必须校验客户端的证书 可以根据实际情况选用其他参数 43 | ClientAuth: tls.RequireAndVerifyClientCert, // NOTE: this is optional! 44 | // 设置根证书的集合,校验方式使用 ClientAuth 中设定的模式 45 | ClientCAs: certPool, 46 | }) 47 | 48 | s := grpc.NewServer(grpc.Creds(creds)) 49 | 50 | pb.RegisterOrderManagementServer(s, &server{}) 51 | 52 | if err := s.Serve(l); err != nil { 53 | panic(err) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /10-secure/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/secure/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &server{} 14 | 15 | var orders = map[string]pb.Order{ 16 | "101": { 17 | Id: "101", 18 | Items: []string{}, 19 | Description: "example", 20 | Price: 0, 21 | Destination: "example", 22 | }, 23 | } 24 | 25 | type server struct { 26 | pb.UnimplementedOrderManagementServer 27 | } 28 | 29 | func (s *server) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 30 | log.Print("GetOrder Request -> : ", orderId) 31 | 32 | ord, exists := orders[orderId.Value] 33 | if exists { 34 | return &ord, status.New(codes.OK, "").Err() 35 | } 36 | 37 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 38 | } 39 | -------------------------------------------------------------------------------- /10-secure/x509/client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEBTCCAu2gAwIBAgIJALVfI+woFJkoMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYD 3 | VQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEQMA4G 4 | A1UEChMHZXhhbXBsZTEQMA4GA1UECxMHZXhhbXBsZTEYMBYGA1UEAxMPd3d3LmV4 5 | YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFpbC5jb20w 6 | HhcNMjIxMjA0MDg1NjE5WhcNMjMwMTAzMDg1NjE5WjCBhzELMAkGA1UEBhMCQ04x 7 | EDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0JlaWppbmcxFDASBgNVBAoTC2V4 8 | YW1wbGUuY29tMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0B 9 | CQEWFWxpYW5nLncudEBmb3htYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP 10 | ADCCAQoCggEBANqHrknTOBAsNoYcnoEYeywo6sfzunWU3dusbs/B/K0FIwqJCl3T 11 | /b38dr3/XCvqIIxsNfxSuV4pLBcvq3MYIXtLMSvwdcCymGW3cm0EHbYrEinKpMca 12 | RqJnllHkS5BzqBEdfbEC7oKktRNGzlaybC9m198XMLPdEKp5PvkMd+K96qGUXXu6 13 | NKgDxU9SymG2DpZqrhciZucocMj6GU+RIpOxUKDyNK8WWbaHwZt8zcABf6NCyMCO 14 | 47BeaOMggQyWfV6VTkSvySfx3j4Ay8qY2QleOUY03BOidTwHoJsZpZgA/ffM7FpN 15 | oDUKfas55uLavk2HWA2ijCpx4Lx87VqhxNkCAwEAAaNkMGIwCQYDVR0TBAIwADAL 16 | BgNVHQ8EBAMCBeAwSAYDVR0RBEEwP4IPd3d3LmV4YW1wbGUuY29tgglsb2NhbGhv 17 | c3SCCTEyNy4wLjAuMYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0B 18 | AQUFAAOCAQEAP5Ho45oj2Sp3+j2lTU4q4InMeQ4tcwp0gwMyJc6/tEi85OvzVZEe 19 | 2aPk1Xn1doQckYSluDS1pFBlFW37SNG53AYSP8VM1yNOSmTafcZX1qqPazQwZfYO 20 | ZeqTS0cR4zpZ+vJING2He8cqB1g2rnr83tBd10O603ZEwDgy2tqnh2xwf9WWGQmG 21 | 4/sW5QR+XxPOQpXSl9S3DVclKvx4dsn/BaR4+Q85BgTSgieNHktXl/ea5DTvQrNx 22 | 7DjPQ1mdmLrfEuYk/mWM4ZeDhmL/9Gs1S5EdlVZlWeqmYvoU+CbDCdgXS8AgKw2P 23 | IOUSLGfwuDtVRvHDP8A+jxjTlHLHT0WoZg== 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /10-secure/x509/client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIDQDCCAigCAQAwgYcxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAw 3 | DgYDVQQHEwdCZWlqaW5nMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEYMBYGA1UEAxMP 4 | d3d3LmV4YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFp 5 | bC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDah65J0zgQLDaG 6 | HJ6BGHssKOrH87p1lN3brG7PwfytBSMKiQpd0/29/Ha9/1wr6iCMbDX8UrleKSwX 7 | L6tzGCF7SzEr8HXAsphlt3JtBB22KxIpyqTHGkaiZ5ZR5EuQc6gRHX2xAu6CpLUT 8 | Rs5WsmwvZtffFzCz3RCqeT75DHfiveqhlF17ujSoA8VPUsphtg6Waq4XImbnKHDI 9 | +hlPkSKTsVCg8jSvFlm2h8GbfM3AAX+jQsjAjuOwXmjjIIEMln1elU5Er8kn8d4+ 10 | AMvKmNkJXjlGNNwTonU8B6CbGaWYAP33zOxaTaA1Cn2rOebi2r5Nh1gNoowqceC8 11 | fO1aocTZAgMBAAGgczBxBgkqhkiG9w0BCQ4xZDBiMAkGA1UdEwQCMAAwCwYDVR0P 12 | BAQDAgXgMEgGA1UdEQRBMD+CD3d3dy5leGFtcGxlLmNvbYIJbG9jYWxob3N0ggkx 13 | MjcuMC4wLjGHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQAD 14 | ggEBANZXWW4d+3q+rOox2yx5uhoQmDaDSfYfGi+WOqAFP4hhTztuRVQxvGr1RPF8 15 | +Zxk1qoMrDIPczY96AmrpHNIBmF65Kd8SUXhgRqAOBU1owMOj0rMvTek7oDgBU20 16 | zv6JZYDuI6YJ1sFXgEvlcpiRfITZ/ybeaxUovp9NPKI4pG2pg+4O8I/Pin3DpHXO 17 | 9gJlMtMpepCYdGLWKlmpqHa9IHD5n88Df9gFBQgzJgmAjdRCqN0irxie1Xf8jbEa 18 | ppUweV8mEn8vLRq3+bjlEVxOH/Pusdp9TeZOkoEoAI+34GXg0RVdtBG7PY0o1QrY 19 | WzvsB4hRDTxFIc9sXVUalFTmzXs= 20 | -----END CERTIFICATE REQUEST----- 21 | -------------------------------------------------------------------------------- /10-secure/x509/client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDah65J0zgQLDaG 3 | HJ6BGHssKOrH87p1lN3brG7PwfytBSMKiQpd0/29/Ha9/1wr6iCMbDX8UrleKSwX 4 | L6tzGCF7SzEr8HXAsphlt3JtBB22KxIpyqTHGkaiZ5ZR5EuQc6gRHX2xAu6CpLUT 5 | Rs5WsmwvZtffFzCz3RCqeT75DHfiveqhlF17ujSoA8VPUsphtg6Waq4XImbnKHDI 6 | +hlPkSKTsVCg8jSvFlm2h8GbfM3AAX+jQsjAjuOwXmjjIIEMln1elU5Er8kn8d4+ 7 | AMvKmNkJXjlGNNwTonU8B6CbGaWYAP33zOxaTaA1Cn2rOebi2r5Nh1gNoowqceC8 8 | fO1aocTZAgMBAAECggEBAJVkulbH6gTMZP3sJMP2e4Yl9tN5INhvS/h4ekzXvih+ 9 | YYU7SHX6jfZK2NZs85Ml/NhixclYuFbR6M11Dk2hiooiTlxOiAGTVrH65mP2s2Ut 10 | Lr6ZRWrD4NP34wDbBHmdR6FjuuC/M1Tmys+B0V/dnC4PrbZawTXFBDa2qsFRr8e2 11 | cA3saic9dIkzPrEmIbLo1/gi3WBOEwSb1DuQel+lW7GvQKJHEwOTeGcy8cSQr3hg 12 | 4+F3+mWdb+bj8v+AoNkpjSusUB+48vGwTOj76vDTOj5DCQNN99eTJsYu5jAkSliS 13 | mDfkt6B13ux05LWXrnaOulBr/PgJjAx+OHg+CJAHp3ECgYEA+W232fslJ0LHtLd2 14 | jinUJ/A4Bdn63oOfQoj6HPwfIlzX0Vw3Zcy3r0evXeVXfqxcIQd1Rg1PchJ8eCV6 15 | /TBVTovfiUs05fHBg3AhiTAY1Cw9BqbyzgMOVdWLaB8tK9/SLgorw2RYs6+G4tnW 16 | YdVyKkUCR7fg1o03XgfD2QRmJk0CgYEA4EmQ2YhjwQlsxU9ujsc6z1wFXDKBwOJM 17 | t5B0DugoKfFRQjw5L8P2nZ5cL8N03/JZWDfpwsc5fiDYmUrrUeBX7wsQQYanLBVJ 18 | bfp5z2yTk8nfSsF0skjyQGKBJ8PUmZkd4J2ioCEAn7DGbBTFRGR50tQGQL+tlaZ+ 19 | tkEPLAPQdr0CgYB6+w7wKjUKY5HF18NbmuIhAv8MW4qm1azbiGARlHnhXneGoXoq 20 | 9kIG6Uhc+mwmZ+NQ4bV/4aYvL1AxiQFX/tHA1ZRUxEEDsyxfmxTd6FoFmv5H3l7P 21 | FpCl35FJuD10aXne+2LShxJ5He1awl9Cg5QzpSzXoaD5CE2pThjRUqru7QKBgQCE 22 | TKC20G8XNPoGQV6Ttg2It10qD1jecB6UwQ7UpDjc1M375g5NkKhuPTVfr0nHt+rf 23 | 0MuA64eMUM+zTLAWceEszjfejxEZPc08pF0p73/100R1kjvF1qWfOPu6exdzKxCm 24 | qBV/ozf8+odwxae/Og1qQUsW8nnwJm/kDehnLDDReQKBgQDZHkCcxB1xMQpESWzE 25 | LqZxk/qu9JDhI4Zt/1kypVWyf+lBPnQgjOeqsZGHnDB0s/u5NTCZ7aCUwcbt1r+f 26 | 0xE+27dIWlWD4vfI0DOLqjsFR1q2U/9Kos2jAJQ35IXM0LlWAembgwlnNprFquhz 27 | kYc7CvrO5ifzJretOGZbRcVHYQ== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /10-secure/x509/rootCA.srl: -------------------------------------------------------------------------------- 1 | B55F23EC2814992C 2 | -------------------------------------------------------------------------------- /10-secure/x509/rootCa.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIExTCCA62gAwIBAgIUQtBScgkFMyimWQ0NIWheOxaBpaswDQYJKoZIhvcNAQEL 3 | BQAwgZUxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdC 4 | ZWlqaW5nMRAwDgYDVQQKEwdleGFtcGxlMRAwDgYDVQQLEwdleGFtcGxlMRgwFgYD 5 | VQQDEw93d3cuZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0BCQEWFWxpYW5nLncudEBm 6 | b3htYWlsLmNvbTAeFw0yMjEwMDgxNTA4MTZaFw0yMzEwMDgxNTA4MTZaMIGVMQsw 7 | CQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEQ 8 | MA4GA1UEChMHZXhhbXBsZTEQMA4GA1UECxMHZXhhbXBsZTEYMBYGA1UEAxMPd3d3 9 | LmV4YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFpbC5j 10 | b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSdqFk3Wf3c1qkUMHa 11 | K/sd6RfHfW+LAdkqd/sVI0qP5GxWeu5J3TSj/ciUFUS/czv73crpqgZ09brIFeyZ 12 | 1US/4KBPkIX7UcHdBxPjh4iyUCv20VAbVRDYATirnXBh3VpqR7ohi7q+zJTmjH+4 13 | 7HjJe+suHUXc0r7SlYuqTjZl3VuM8PeGuBf8prHe5Dha2J6cS9fsUHC3Q4X6PUgx 14 | 8FQ1sPxC2CmtBNGvPKQmOq3LSzhICkfQWhSf7Zghv6K5L6FLhSJgwNO4jzfAgvBU 15 | SBOTwZhMGn3ILn5I7IdcRhJpb5KPhykN44ecZZboGu7W6XbWHs21lZfxum0nzXES 16 | GflFAgMBAAGjggEJMIIBBTAdBgNVHQ4EFgQUV+UFrPWR8GI+QntWDcvCTysZinww 17 | gdUGA1UdIwSBzTCByoAUV+UFrPWR8GI+QntWDcvCTysZinyhgZukgZgwgZUxCzAJ 18 | BgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdCZWlqaW5nMRAw 19 | DgYDVQQKEwdleGFtcGxlMRAwDgYDVQQLEwdleGFtcGxlMRgwFgYDVQQDEw93d3cu 20 | ZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0BCQEWFWxpYW5nLncudEBmb3htYWlsLmNv 21 | bYIUQtBScgkFMyimWQ0NIWheOxaBpaswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B 22 | AQsFAAOCAQEALPpoXM9MJz0f6rLdxEkcER0aaRyrGzKdJZUMvOagsVtslOICvd7v 23 | NVwXwwJcberLCi8rRCzQjO57GtqgUG1rE8Q0Da5CM/Aa/xhg/lGYKfIHCSf0hAuq 24 | 2Hi5yF4IMz8zyjF/KZGhsntQbnhxZAy7XrxE+LeniWpFlTDzsteD+sFRSv+f2ZH7 25 | TzsVTnp5GP6cahO3CkUPH1RnlE+4HQUHPqXzRxd9q0GfwKnr0GynsXyAxUfTm5Pb 26 | AEysUFyEjUKMswrPh16X0qIvmWqNctorEPmiNB1+rcMPWwyPffiWA2yMPhYoDx60 27 | Ekeqs4rk7p9IVmMGh4E/bHalI274b+pR8g== 28 | -----END CERTIFICATE----- 29 | -------------------------------------------------------------------------------- /10-secure/x509/rootCa.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSdqFk3Wf3c1qk 3 | UMHaK/sd6RfHfW+LAdkqd/sVI0qP5GxWeu5J3TSj/ciUFUS/czv73crpqgZ09brI 4 | FeyZ1US/4KBPkIX7UcHdBxPjh4iyUCv20VAbVRDYATirnXBh3VpqR7ohi7q+zJTm 5 | jH+47HjJe+suHUXc0r7SlYuqTjZl3VuM8PeGuBf8prHe5Dha2J6cS9fsUHC3Q4X6 6 | PUgx8FQ1sPxC2CmtBNGvPKQmOq3LSzhICkfQWhSf7Zghv6K5L6FLhSJgwNO4jzfA 7 | gvBUSBOTwZhMGn3ILn5I7IdcRhJpb5KPhykN44ecZZboGu7W6XbWHs21lZfxum0n 8 | zXESGflFAgMBAAECggEAXmk3Fz82/0sw8xsDCvLF0HIa57N+URZALAvsh1vwe8IV 9 | U2oL8PiZP6N90egEkfmIhADHoLBT+y2sX0tuesev8n86itajM81GMPeW1W+cQ5kx 10 | T6Qv0kMDrlJF8L5Mhqo8gAazGY9L84FknlOSjAsQWBoNsv8QsvGbBm5tW7WAM4sb 11 | zk9l1IMYIQmUKXyon9ZeK3ynLpo0bFcYc+gRPWmjIXA/p5Rnl43VnuI0hSRvpkRW 12 | wdC+lFHqd9nUGFhxDznXhRXe5yKQKvWs/gjKhCjnIK3aeL51/9CrBNK8FaVKd+AY 13 | wdOCZD0emVyo052M0RgUeeBAFkf4XM0eMuo1IqCzQQKBgQDuULzKRwGInC6zX4of 14 | Mh3huFRaerZfk70jAxQis0Xpt0a1GA205iD5lpf8yhfOawminihMU3bpgXa0f4PO 15 | wm21+FisszlFkQv7J6wMCeSgqq7zzFPP+3vhIb/ksokkjzPmxoykdj9fp92RJqRt 16 | fDfm2dh0tXDE2UGwo1MbOquJ8QKBgQDiFMpm8olnlv/Xqz2fdHGTNSajBjkLbjCM 17 | DrXzMckojs8ABHMxqpp6xMwoTTqYKFxuNRJ9bvfRARTvlEvs1hHBHnHVrB+d2ZRS 18 | YLGMSkn+V9GKukRO6s/mS0mkTjUPhiVWumh8kONktIbjiltXiujTZItL0jFA8jtJ 19 | HO4dDz2wlQKBgALEazzKEEl+zsgEbv0nvtMVKd2XGTEI7SRP79brT/+Dwk1uBxK3 20 | rWBYkFE+I4KhGY6K2ZrxSSsy9qbn6CbpeQ6o4Ja4ygx1v7bd4hCNuNrowHlSQRLk 21 | L68QjkLgk9kZ1Jd0bMOoH9pDf74kvboLvDZxByNry/BtOWcMrnVdfApxAoGAIbv+ 22 | c5wPGrDyXgkEOe3TIKcWq8665lS707pCNhagsHeWtab0VV3ijR0eZYkYjCnBmQQ8 23 | TREo0zv5FsKnDaDnp0xWqg5z7UbRFfWtqIRRRC1wa+XdWXU6Ll/fji/JRRa8LZPF 24 | EYlBFP7G/d7gQFDO6vQewOKNTOaYKBG0CgwDJX0CgYEA6Ya2nhe4zdAYyad1X08z 25 | IUacHnaW6f0lnybbSEPzhVGJnqdCZdvFF6hjMyp+ABwjgzNaseLTrZAlsXWrOFEp 26 | GcgqhH89H135hlMPNKfvr2gKvV+8FyReeSFT+XhHj8ey79ndHZU7JFejUam2tLpE 27 | EVaQ4PwbPNoB2bBrhRCApAk= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /10-secure/x509/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEATCCAumgAwIBAgIJALVfI+woFJksMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYD 3 | VQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEQMA4G 4 | A1UEChMHZXhhbXBsZTEQMA4GA1UECxMHZXhhbXBsZTEYMBYGA1UEAxMPd3d3LmV4 5 | YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFpbC5jb20w 6 | HhcNMjIxMjA0MDkyNzIwWhcNMjMwMTAzMDkyNzIwWjCBgzELMAkGA1UEBhMCQ04x 7 | EDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0JlaWppbmcxEDAOBgNVBAoTB2V4 8 | YW1wbGUxGDAWBgNVBAMTD3d3dy5leGFtcGxlLmNvbTEkMCIGCSqGSIb3DQEJARYV 9 | bGlhbmcudy50QGZveG1haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 10 | CgKCAQEAzlMtteD/T3owzEnTgDhGTh42va4krJQ/7OLJzmuVZELHijml2Wjfdobd 11 | Mb4MQr7sxIeDaGCZ/SKAEoP1qklg35fz6jDRGvP4nkZtoH1aTLOvADnvLqQqWiA/ 12 | /8ZSxv8LxPLrzfUyerIxKciFarPYrhpJ8TSb7wvVpr5Ni54na81KLNt4SaKMKNwn 13 | NnE5/PTwNGiF0/UeO0w87l21g6/QsmztYCH/xeyHe8mLwqbS06vyp94ZKxOQ6qTN 14 | /ciEZyQA2S7Qkw8Zau4N8Yx+W/kx51tCO5ZM18otHHklVpvrYIh+TS/QeQ29r+8Z 15 | zaLzsK9kQGc/Wn2Xt4HQwsFHe1eU0QIDAQABo2QwYjAJBgNVHRMEAjAAMAsGA1Ud 16 | DwQEAwIF4DBIBgNVHREEQTA/gg93d3cuZXhhbXBsZS5jb22CCWxvY2FsaG9zdIIJ 17 | MTI3LjAuMC4xhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBBQUA 18 | A4IBAQBxqJTmexqNW7AGU5yA54WQKZ3RWgbsKKBibaEQkMw44zNfuUFm2ZjOTBTg 19 | qAunXKsH2bkgQcLU+0RvwG6bcFZMcD20o2BHLCXYWLadZQAcLcLlPefDY+7Bmr81 20 | kMGuWS3H5FlF/fp9YT8T21rXomNoJxuJVxn8qcLsrjCW2zwFIi8XOgUQzxYVQtxD 21 | Nm8cGXghbpsBDqJ4D+hGWbdphT4qMqRfbnWQUBfSWRklckO8KBXCowc4ND4MYHfm 22 | tp25cdQ47sYW91uGTdeBzmJjlx952gZAPza6xIPlGRsiQN2xKUPqVS/09scwwyE9 23 | py8r7w9qw7KhMJZNoZty49n0cc6L 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /10-secure/x509/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIDPDCCAiQCAQAwgYMxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAw 3 | DgYDVQQHEwdCZWlqaW5nMRAwDgYDVQQKEwdleGFtcGxlMRgwFgYDVQQDEw93d3cu 4 | ZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0BCQEWFWxpYW5nLncudEBmb3htYWlsLmNv 5 | bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5TLbXg/096MMxJ04A4 6 | Rk4eNr2uJKyUP+ziyc5rlWRCx4o5pdlo33aG3TG+DEK+7MSHg2hgmf0igBKD9apJ 7 | YN+X8+ow0Rrz+J5GbaB9WkyzrwA57y6kKlogP//GUsb/C8Ty6831MnqyMSnIhWqz 8 | 2K4aSfE0m+8L1aa+TYueJ2vNSizbeEmijCjcJzZxOfz08DRohdP1HjtMPO5dtYOv 9 | 0LJs7WAh/8Xsh3vJi8Km0tOr8qfeGSsTkOqkzf3IhGckANku0JMPGWruDfGMflv5 10 | MedbQjuWTNfKLRx5JVab62CIfk0v0HkNva/vGc2i87CvZEBnP1p9l7eB0MLBR3tX 11 | lNECAwEAAaBzMHEGCSqGSIb3DQEJDjFkMGIwCQYDVR0TBAIwADALBgNVHQ8EBAMC 12 | BeAwSAYDVR0RBEEwP4IPd3d3LmV4YW1wbGUuY29tgglsb2NhbGhvc3SCCTEyNy4w 13 | LjAuMYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEA 14 | FfBCKXmQlyei4APH1jJi/81tBtvrN4Qah5Y0VzvaLiINWijM1grGR6KSRivnAhuZ 15 | laGBDKQbNZobNQCHJj09t6tVZHu2DunxdRC7RyUpRT11oe7M423mjUxTwH3B61uZ 16 | U3qjPg79hfZ9n/WVu6N3OTTShGjnl7XbLT2FEyynfBVyTLZ9/n5Npq+Xr4Ls11Zv 17 | TkqH6zEtbuWa1c2kB/1p3Czn7C5PNbitW10zKxC1oFrfnS60sIarBEhGpVQRvVBm 18 | PTQS3/AkeFVt8IpItzwUBoac8Wuo2UzwJuPFn9YCuWgJUTT1QzAl3A3OX2+7V+7H 19 | vq1jXM+0Ehyhhqfz3HTB3A== 20 | -----END CERTIFICATE REQUEST----- 21 | -------------------------------------------------------------------------------- /10-secure/x509/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDOUy214P9PejDM 3 | SdOAOEZOHja9riSslD/s4snOa5VkQseKOaXZaN92ht0xvgxCvuzEh4NoYJn9IoAS 4 | g/WqSWDfl/PqMNEa8/ieRm2gfVpMs68AOe8upCpaID//xlLG/wvE8uvN9TJ6sjEp 5 | yIVqs9iuGknxNJvvC9Wmvk2LnidrzUos23hJoowo3Cc2cTn89PA0aIXT9R47TDzu 6 | XbWDr9CybO1gIf/F7Id7yYvCptLTq/Kn3hkrE5DqpM39yIRnJADZLtCTDxlq7g3x 7 | jH5b+THnW0I7lkzXyi0ceSVWm+tgiH5NL9B5Db2v7xnNovOwr2RAZz9afZe3gdDC 8 | wUd7V5TRAgMBAAECggEBALq7yVkdI7UYz+V0w7j+NZMqAT02yPZwzlJlB2SNNg4h 9 | 6lqNxi64nda2RKdqa8pU5hEQ3LuxAm15thQL3mGaO9Thv94rBHWybUdCUqG4Eevt 10 | i+tWg8Tgy3v6SDIDmpOD7XD4srYavu8RKzG3zBhAYVFhdZ6akK6PNXTOM3yzTNZg 11 | uulamJcPS4dGWBR82Z5CdDecvLAI529G9u41zcRDge5vjwWjHWbjgmDy0mHxYivp 12 | u9DJcekBALZobauv6FDVi8Z3xSmECeCp+yiqCQmx7DLFZidzSG5D/Ey+kbicn8Sy 13 | 627avmq+m3/zH9WyZVcxQO/yLSSyn5Yd4JzfP3ujtCkCgYEA+UXRpBe9ULuYBx7K 14 | o6WaV+G8j7SDJaCNFcpJCxVceeGRPIKkXksnYenlZFQVLD71b/fj2YWFFsqFNw0Y 15 | iMFuzIibYI2MuOIkQcMZwlNkJ0ju8oZ5l7OehLE9/qjxwrUcmFnBjsr/kCXhNQqJ 16 | J0OESMCI7CiHM4nY7D9WbZFs+zsCgYEA0+SkDIU2Vgun3NHFPTgqgzekBvyJ/w95 17 | 0c7sMLXhKZfJELf753oGGOecVqVSqY2pNa//fDlth6McBjTdcHGssMel5zCRvG+9 18 | Hi7SpW+gjpuwQALCeAmBITiOrC0bPtKDUP0vIjodPV41ounZVIDj10IVkLQFr6Cx 19 | QzZKdCWed2MCgYEAuqioklrgfbrr3bEWBrL0P4ie/XErn5p46289gRou1GmvqwMc 20 | +CsIw441Iwq/jBFdEsoqiXEtNuLSHGYnEAjg4jINP6DfVnaotcHV4Sk23yADJgLC 21 | vHFZa32Zsb9qweWDEyZrBXVHJ/bljCVmjMtHHH9oSIcUrugzUr0fCA8U748CgYEA 22 | lv8B4GI1fE/GCVf7BEs4EFXgL5JbDEWM+/RG39dcYvVlNOLHQgb0vV6fTCd3ppfq 23 | kvWeTHnoEZYsbEfT3UNEWp2LHhrAX9YIoK+hMH9BnR5ZFORijIPJX1EcapmiJryB 24 | E3+4zN045PhzpGqcktleg5D2KS4AN019xHW1zNrZ+B0CgYEAurkm1+c6XRqaIW6J 25 | 7MH/gqA8R9Tgbe0PrBkJ1oEXSbN252GxU/3bBn14F5HnOBZO3TqPLdLS9+LX4HG0 26 | n5qS7Q3qFFASsqrxaGR/8CkAiqSb7/MJAyjJC+mNs529hikXbQTSucrguFVOGa0x 27 | tMkMUiz+w6zJFq4z4FqjYcikuoA= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /11-authentication/00-basic-authentication/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/base64" 6 | "log" 7 | "time" 8 | 9 | pb "github.com/liangwt/note/grpc/authentication/ecommerce" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/credentials" 12 | "google.golang.org/grpc/credentials/insecure" 13 | "google.golang.org/protobuf/types/known/wrapperspb" 14 | ) 15 | 16 | var _ credentials.PerRPCCredentials = BasicAuthentication{} 17 | 18 | type BasicAuthentication struct { 19 | password string 20 | username string 21 | } 22 | 23 | func (b BasicAuthentication) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 24 | auth := b.username + ":" + b.password 25 | enc := base64.StdEncoding.EncodeToString([]byte(auth)) 26 | 27 | return map[string]string{ 28 | "authorization": "Basic " + enc, 29 | }, nil 30 | } 31 | 32 | func (b BasicAuthentication) RequireTransportSecurity() bool { 33 | return true 34 | } 35 | 36 | func main() { 37 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 38 | defer cancel() 39 | 40 | auth := BasicAuthentication{ 41 | username: "admin", 42 | password: "admin", 43 | } 44 | 45 | creds, err := credentials.NewClientTLSFromFile("./x509/rootCa.crt", "www.example.com") 46 | if err != nil { 47 | panic(err) 48 | } 49 | 50 | conn, err := grpc.Dial("localhost:8009", 51 | grpc.WithTransportCredentials(creds), 52 | grpc.WithPerRPCCredentials(auth)) 53 | if err != nil { 54 | panic(err) 55 | } 56 | defer conn.Close() 57 | 58 | client := pb.NewOrderManagementClient(conn) 59 | 60 | // Get Order 61 | retrievedOrder, err := client.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 62 | if err != nil { 63 | panic(err) 64 | } 65 | 66 | log.Printf("GetOrder Response -> : %+v\n", retrievedOrder) 67 | } 68 | -------------------------------------------------------------------------------- /11-authentication/00-basic-authentication/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/base64" 6 | "net" 7 | "strings" 8 | 9 | pb "github.com/liangwt/note/grpc/authentication/ecommerce" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/credentials" 13 | "google.golang.org/grpc/metadata" 14 | "google.golang.org/grpc/status" 15 | ) 16 | 17 | var ( 18 | errMissingMetadata = status.Errorf(codes.InvalidArgument, "missing metadata") 19 | errInvalidToken = status.Errorf(codes.Unauthenticated, "invalid credentials") 20 | ) 21 | 22 | func ensureValidBasicCredentials(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 23 | md, ok := metadata.FromIncomingContext(ctx) 24 | if !ok { 25 | return nil, errMissingMetadata 26 | } 27 | 28 | authorization := md["authorization"] 29 | 30 | if len(authorization) < 1 { 31 | return nil, errInvalidToken 32 | } 33 | 34 | token := strings.TrimPrefix(authorization[0], "Basic ") 35 | if token != base64.StdEncoding.EncodeToString([]byte("admin:admin")) { 36 | return nil, errInvalidToken 37 | } 38 | 39 | return handler(ctx, req) 40 | } 41 | 42 | func main() { 43 | l, err := net.Listen("tcp", ":8009") 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | creds, err := credentials.NewServerTLSFromFile("./x509/server.crt", "./x509/server.key") 49 | s := grpc.NewServer( 50 | grpc.UnaryInterceptor(ensureValidBasicCredentials), 51 | grpc.Creds(creds), 52 | ) 53 | 54 | pb.RegisterOrderManagementServer(s, &server{}) 55 | 56 | if err := s.Serve(l); err != nil { 57 | panic(err) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /11-authentication/00-basic-authentication/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/authentication/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &server{} 14 | 15 | var orders = map[string]pb.Order{ 16 | "101": { 17 | Id: "101", 18 | Items: []string{}, 19 | Description: "example", 20 | Price: 0, 21 | Destination: "example", 22 | }, 23 | } 24 | 25 | type server struct { 26 | pb.UnimplementedOrderManagementServer 27 | } 28 | 29 | func (s *server) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 30 | log.Print("GetOrder Request -> : ", orderId) 31 | 32 | ord, exists := orders[orderId.Value] 33 | if exists { 34 | return &ord, status.New(codes.OK, "").Err() 35 | } 36 | 37 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 38 | } 39 | -------------------------------------------------------------------------------- /11-authentication/01-jwt/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | "github.com/golang-jwt/jwt/v4" 9 | pb "github.com/liangwt/note/grpc/authentication/ecommerce" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/credentials" 12 | "google.golang.org/protobuf/types/known/wrapperspb" 13 | ) 14 | 15 | var _ credentials.PerRPCCredentials = JwtAuthentication{} 16 | 17 | type JwtAuthentication struct { 18 | Key []byte 19 | } 20 | 21 | func (a JwtAuthentication) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 22 | // Create a new token object, specifying signing method and the claims 23 | // you would like it to contain. 24 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{ 25 | ID: "example", 26 | ExpiresAt: jwt.NewNumericDate(time.Now().Add(-2 * time.Hour)), 27 | }) 28 | 29 | // Sign and get the complete encoded token as a string using the secret 30 | tokenString, err := token.SignedString(a.Key) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return map[string]string{ 36 | "authorization": "Bearer " + tokenString, 37 | }, nil 38 | } 39 | 40 | func (b JwtAuthentication) RequireTransportSecurity() bool { 41 | return true 42 | } 43 | 44 | func main() { 45 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 46 | defer cancel() 47 | 48 | creds, err := credentials.NewClientTLSFromFile("./x509/rootCa.crt", "www.example.com") 49 | if err != nil { 50 | panic(err) 51 | } 52 | 53 | jwtAuth := JwtAuthentication{[]byte("154a8b3aa89d3d4c49826f6dbbbe5542b5a9fbbb")} 54 | 55 | conn, err := grpc.Dial("localhost:8009", 56 | grpc.WithTransportCredentials(creds), 57 | grpc.WithPerRPCCredentials(jwtAuth)) 58 | if err != nil { 59 | panic(err) 60 | } 61 | defer conn.Close() 62 | 63 | client := pb.NewOrderManagementClient(conn) 64 | 65 | // Get Order 66 | retrievedOrder, err := client.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 67 | if err != nil { 68 | panic(err) 69 | } 70 | 71 | log.Printf("GetOrder Response -> : %+v\n", retrievedOrder) 72 | } 73 | -------------------------------------------------------------------------------- /11-authentication/01-jwt/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net" 7 | "strings" 8 | 9 | "github.com/golang-jwt/jwt/v4" 10 | pb "github.com/liangwt/note/grpc/authentication/ecommerce" 11 | "google.golang.org/grpc" 12 | "google.golang.org/grpc/codes" 13 | "google.golang.org/grpc/credentials" 14 | "google.golang.org/grpc/metadata" 15 | "google.golang.org/grpc/status" 16 | ) 17 | 18 | var ( 19 | errMissingMetadata = status.Errorf(codes.InvalidArgument, "missing metadata") 20 | ) 21 | 22 | func ensureValidBasicCredentials(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 23 | md, ok := metadata.FromIncomingContext(ctx) 24 | if !ok { 25 | return nil, errMissingMetadata 26 | } 27 | 28 | tokenString := strings.TrimPrefix(md["authorization"][0], "Bearer ") 29 | 30 | token, err := jwt.ParseWithClaims(tokenString, &jwt.RegisteredClaims{}, func(token *jwt.Token) (interface{}, error) { 31 | // Don't forget to validate the alg is what you expect: 32 | if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { 33 | return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) 34 | } 35 | 36 | return []byte("154a8b3aa89d3d4c49826f6dbbbe5542b5a9fbbb"), nil 37 | }) 38 | 39 | claims, ok := token.Claims.(*jwt.RegisteredClaims) 40 | if !ok || !token.Valid { 41 | return nil, status.Errorf(codes.Unauthenticated, err.Error()) 42 | } 43 | 44 | fmt.Println(claims.ID) 45 | 46 | return handler(ctx, req) 47 | } 48 | 49 | func main() { 50 | l, err := net.Listen("tcp", ":8009") 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | creds, err := credentials.NewServerTLSFromFile("./x509/server.crt", "./x509/server.key") 56 | s := grpc.NewServer( 57 | grpc.UnaryInterceptor(ensureValidBasicCredentials), 58 | grpc.Creds(creds), 59 | ) 60 | 61 | pb.RegisterOrderManagementServer(s, &server{}) 62 | 63 | if err := s.Serve(l); err != nil { 64 | panic(err) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /11-authentication/01-jwt/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/authentication/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &server{} 14 | 15 | var orders = map[string]pb.Order{ 16 | "101": { 17 | Id: "101", 18 | Items: []string{}, 19 | Description: "example", 20 | Price: 0, 21 | Destination: "example", 22 | }, 23 | } 24 | 25 | type server struct { 26 | pb.UnimplementedOrderManagementServer 27 | } 28 | 29 | func (s *server) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 30 | log.Print("GetOrder Request -> : ", orderId) 31 | 32 | ord, exists := orders[orderId.Value] 33 | if exists { 34 | return &ord, status.New(codes.OK, "").Err() 35 | } 36 | 37 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 38 | } 39 | -------------------------------------------------------------------------------- /11-authentication/ecommerce/product.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc v3.19.4 5 | // source: product.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Order struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` 30 | Items []string `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` 31 | Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` 32 | Price float32 `protobuf:"fixed32,4,opt,name=price,proto3" json:"price,omitempty"` 33 | Destination string `protobuf:"bytes,5,opt,name=destination,proto3" json:"destination,omitempty"` 34 | } 35 | 36 | func (x *Order) Reset() { 37 | *x = Order{} 38 | if protoimpl.UnsafeEnabled { 39 | mi := &file_product_proto_msgTypes[0] 40 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 41 | ms.StoreMessageInfo(mi) 42 | } 43 | } 44 | 45 | func (x *Order) String() string { 46 | return protoimpl.X.MessageStringOf(x) 47 | } 48 | 49 | func (*Order) ProtoMessage() {} 50 | 51 | func (x *Order) ProtoReflect() protoreflect.Message { 52 | mi := &file_product_proto_msgTypes[0] 53 | if protoimpl.UnsafeEnabled && x != nil { 54 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 55 | if ms.LoadMessageInfo() == nil { 56 | ms.StoreMessageInfo(mi) 57 | } 58 | return ms 59 | } 60 | return mi.MessageOf(x) 61 | } 62 | 63 | // Deprecated: Use Order.ProtoReflect.Descriptor instead. 64 | func (*Order) Descriptor() ([]byte, []int) { 65 | return file_product_proto_rawDescGZIP(), []int{0} 66 | } 67 | 68 | func (x *Order) GetId() string { 69 | if x != nil { 70 | return x.Id 71 | } 72 | return "" 73 | } 74 | 75 | func (x *Order) GetItems() []string { 76 | if x != nil { 77 | return x.Items 78 | } 79 | return nil 80 | } 81 | 82 | func (x *Order) GetDescription() string { 83 | if x != nil { 84 | return x.Description 85 | } 86 | return "" 87 | } 88 | 89 | func (x *Order) GetPrice() float32 { 90 | if x != nil { 91 | return x.Price 92 | } 93 | return 0 94 | } 95 | 96 | func (x *Order) GetDestination() string { 97 | if x != nil { 98 | return x.Destination 99 | } 100 | return "" 101 | } 102 | 103 | var File_product_proto protoreflect.FileDescriptor 104 | 105 | var file_product_proto_rawDesc = []byte{ 106 | 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 107 | 0x09, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 108 | 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 109 | 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 0x0a, 0x05, 0x4f, 110 | 0x72, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 111 | 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 112 | 0x03, 0x28, 0x09, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 113 | 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 114 | 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 115 | 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x70, 0x72, 0x69, 116 | 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 117 | 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 118 | 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x4d, 0x0a, 0x0f, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x6e, 119 | 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x08, 0x67, 0x65, 0x74, 0x4f, 0x72, 120 | 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 121 | 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 122 | 0x65, 0x1a, 0x10, 0x2e, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x2e, 0x4f, 0x72, 123 | 0x64, 0x65, 0x72, 0x42, 0x0c, 0x5a, 0x0a, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 124 | 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 125 | } 126 | 127 | var ( 128 | file_product_proto_rawDescOnce sync.Once 129 | file_product_proto_rawDescData = file_product_proto_rawDesc 130 | ) 131 | 132 | func file_product_proto_rawDescGZIP() []byte { 133 | file_product_proto_rawDescOnce.Do(func() { 134 | file_product_proto_rawDescData = protoimpl.X.CompressGZIP(file_product_proto_rawDescData) 135 | }) 136 | return file_product_proto_rawDescData 137 | } 138 | 139 | var file_product_proto_msgTypes = make([]protoimpl.MessageInfo, 1) 140 | var file_product_proto_goTypes = []interface{}{ 141 | (*Order)(nil), // 0: ecommerce.Order 142 | (*wrapperspb.StringValue)(nil), // 1: google.protobuf.StringValue 143 | } 144 | var file_product_proto_depIdxs = []int32{ 145 | 1, // 0: ecommerce.OrderManagement.getOrder:input_type -> google.protobuf.StringValue 146 | 0, // 1: ecommerce.OrderManagement.getOrder:output_type -> ecommerce.Order 147 | 1, // [1:2] is the sub-list for method output_type 148 | 0, // [0:1] is the sub-list for method input_type 149 | 0, // [0:0] is the sub-list for extension type_name 150 | 0, // [0:0] is the sub-list for extension extendee 151 | 0, // [0:0] is the sub-list for field type_name 152 | } 153 | 154 | func init() { file_product_proto_init() } 155 | func file_product_proto_init() { 156 | if File_product_proto != nil { 157 | return 158 | } 159 | if !protoimpl.UnsafeEnabled { 160 | file_product_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 161 | switch v := v.(*Order); i { 162 | case 0: 163 | return &v.state 164 | case 1: 165 | return &v.sizeCache 166 | case 2: 167 | return &v.unknownFields 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | type x struct{} 174 | out := protoimpl.TypeBuilder{ 175 | File: protoimpl.DescBuilder{ 176 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 177 | RawDescriptor: file_product_proto_rawDesc, 178 | NumEnums: 0, 179 | NumMessages: 1, 180 | NumExtensions: 0, 181 | NumServices: 1, 182 | }, 183 | GoTypes: file_product_proto_goTypes, 184 | DependencyIndexes: file_product_proto_depIdxs, 185 | MessageInfos: file_product_proto_msgTypes, 186 | }.Build() 187 | File_product_proto = out.File 188 | file_product_proto_rawDesc = nil 189 | file_product_proto_goTypes = nil 190 | file_product_proto_depIdxs = nil 191 | } 192 | -------------------------------------------------------------------------------- /11-authentication/ecommerce/product_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.4 5 | // source: product.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) 27 | } 28 | 29 | type orderManagementClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 34 | return &orderManagementClient{cc} 35 | } 36 | 37 | func (c *orderManagementClient) GetOrder(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*Order, error) { 38 | out := new(Order) 39 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/getOrder", in, out, opts...) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return out, nil 44 | } 45 | 46 | // OrderManagementServer is the server API for OrderManagement service. 47 | // All implementations must embed UnimplementedOrderManagementServer 48 | // for forward compatibility 49 | type OrderManagementServer interface { 50 | GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) 51 | mustEmbedUnimplementedOrderManagementServer() 52 | } 53 | 54 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 55 | type UnimplementedOrderManagementServer struct { 56 | } 57 | 58 | func (UnimplementedOrderManagementServer) GetOrder(context.Context, *wrapperspb.StringValue) (*Order, error) { 59 | return nil, status.Errorf(codes.Unimplemented, "method GetOrder not implemented") 60 | } 61 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 62 | 63 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 64 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 65 | // result in compilation errors. 66 | type UnsafeOrderManagementServer interface { 67 | mustEmbedUnimplementedOrderManagementServer() 68 | } 69 | 70 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 71 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 72 | } 73 | 74 | func _OrderManagement_GetOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 75 | in := new(wrapperspb.StringValue) 76 | if err := dec(in); err != nil { 77 | return nil, err 78 | } 79 | if interceptor == nil { 80 | return srv.(OrderManagementServer).GetOrder(ctx, in) 81 | } 82 | info := &grpc.UnaryServerInfo{ 83 | Server: srv, 84 | FullMethod: "/ecommerce.OrderManagement/getOrder", 85 | } 86 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 87 | return srv.(OrderManagementServer).GetOrder(ctx, req.(*wrapperspb.StringValue)) 88 | } 89 | return interceptor(ctx, in, info, handler) 90 | } 91 | 92 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 93 | // It's only intended for direct use with grpc.RegisterService, 94 | // and not to be introspected or modified (even as a copy) 95 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 96 | ServiceName: "ecommerce.OrderManagement", 97 | HandlerType: (*OrderManagementServer)(nil), 98 | Methods: []grpc.MethodDesc{ 99 | { 100 | MethodName: "getOrder", 101 | Handler: _OrderManagement_GetOrder_Handler, 102 | }, 103 | }, 104 | Streams: []grpc.StreamDesc{}, 105 | Metadata: "product.proto", 106 | } 107 | -------------------------------------------------------------------------------- /11-authentication/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/authentication 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/golang-jwt/jwt/v4 v4.4.3 7 | google.golang.org/grpc v1.51.0 8 | google.golang.org/protobuf v1.28.1 9 | ) 10 | 11 | require ( 12 | github.com/golang/protobuf v1.5.2 // indirect 13 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect 14 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect 15 | golang.org/x/text v0.4.0 // indirect 16 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /11-authentication/pb/product.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | service OrderManagement { 10 | rpc getOrder(google.protobuf.StringValue) returns (Order); 11 | } 12 | 13 | message Order { 14 | string id = 1; 15 | repeated string items = 2; 16 | string description = 3; 17 | float price = 4; 18 | string destination = 5; 19 | } -------------------------------------------------------------------------------- /11-authentication/x509/client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEBTCCAu2gAwIBAgIJALVfI+woFJkoMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYD 3 | VQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEQMA4G 4 | A1UEChMHZXhhbXBsZTEQMA4GA1UECxMHZXhhbXBsZTEYMBYGA1UEAxMPd3d3LmV4 5 | YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFpbC5jb20w 6 | HhcNMjIxMjA0MDg1NjE5WhcNMjMwMTAzMDg1NjE5WjCBhzELMAkGA1UEBhMCQ04x 7 | EDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0JlaWppbmcxFDASBgNVBAoTC2V4 8 | YW1wbGUuY29tMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0B 9 | CQEWFWxpYW5nLncudEBmb3htYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP 10 | ADCCAQoCggEBANqHrknTOBAsNoYcnoEYeywo6sfzunWU3dusbs/B/K0FIwqJCl3T 11 | /b38dr3/XCvqIIxsNfxSuV4pLBcvq3MYIXtLMSvwdcCymGW3cm0EHbYrEinKpMca 12 | RqJnllHkS5BzqBEdfbEC7oKktRNGzlaybC9m198XMLPdEKp5PvkMd+K96qGUXXu6 13 | NKgDxU9SymG2DpZqrhciZucocMj6GU+RIpOxUKDyNK8WWbaHwZt8zcABf6NCyMCO 14 | 47BeaOMggQyWfV6VTkSvySfx3j4Ay8qY2QleOUY03BOidTwHoJsZpZgA/ffM7FpN 15 | oDUKfas55uLavk2HWA2ijCpx4Lx87VqhxNkCAwEAAaNkMGIwCQYDVR0TBAIwADAL 16 | BgNVHQ8EBAMCBeAwSAYDVR0RBEEwP4IPd3d3LmV4YW1wbGUuY29tgglsb2NhbGhv 17 | c3SCCTEyNy4wLjAuMYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0B 18 | AQUFAAOCAQEAP5Ho45oj2Sp3+j2lTU4q4InMeQ4tcwp0gwMyJc6/tEi85OvzVZEe 19 | 2aPk1Xn1doQckYSluDS1pFBlFW37SNG53AYSP8VM1yNOSmTafcZX1qqPazQwZfYO 20 | ZeqTS0cR4zpZ+vJING2He8cqB1g2rnr83tBd10O603ZEwDgy2tqnh2xwf9WWGQmG 21 | 4/sW5QR+XxPOQpXSl9S3DVclKvx4dsn/BaR4+Q85BgTSgieNHktXl/ea5DTvQrNx 22 | 7DjPQ1mdmLrfEuYk/mWM4ZeDhmL/9Gs1S5EdlVZlWeqmYvoU+CbDCdgXS8AgKw2P 23 | IOUSLGfwuDtVRvHDP8A+jxjTlHLHT0WoZg== 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /11-authentication/x509/client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIDQDCCAigCAQAwgYcxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAw 3 | DgYDVQQHEwdCZWlqaW5nMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEYMBYGA1UEAxMP 4 | d3d3LmV4YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFp 5 | bC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDah65J0zgQLDaG 6 | HJ6BGHssKOrH87p1lN3brG7PwfytBSMKiQpd0/29/Ha9/1wr6iCMbDX8UrleKSwX 7 | L6tzGCF7SzEr8HXAsphlt3JtBB22KxIpyqTHGkaiZ5ZR5EuQc6gRHX2xAu6CpLUT 8 | Rs5WsmwvZtffFzCz3RCqeT75DHfiveqhlF17ujSoA8VPUsphtg6Waq4XImbnKHDI 9 | +hlPkSKTsVCg8jSvFlm2h8GbfM3AAX+jQsjAjuOwXmjjIIEMln1elU5Er8kn8d4+ 10 | AMvKmNkJXjlGNNwTonU8B6CbGaWYAP33zOxaTaA1Cn2rOebi2r5Nh1gNoowqceC8 11 | fO1aocTZAgMBAAGgczBxBgkqhkiG9w0BCQ4xZDBiMAkGA1UdEwQCMAAwCwYDVR0P 12 | BAQDAgXgMEgGA1UdEQRBMD+CD3d3dy5leGFtcGxlLmNvbYIJbG9jYWxob3N0ggkx 13 | MjcuMC4wLjGHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQAD 14 | ggEBANZXWW4d+3q+rOox2yx5uhoQmDaDSfYfGi+WOqAFP4hhTztuRVQxvGr1RPF8 15 | +Zxk1qoMrDIPczY96AmrpHNIBmF65Kd8SUXhgRqAOBU1owMOj0rMvTek7oDgBU20 16 | zv6JZYDuI6YJ1sFXgEvlcpiRfITZ/ybeaxUovp9NPKI4pG2pg+4O8I/Pin3DpHXO 17 | 9gJlMtMpepCYdGLWKlmpqHa9IHD5n88Df9gFBQgzJgmAjdRCqN0irxie1Xf8jbEa 18 | ppUweV8mEn8vLRq3+bjlEVxOH/Pusdp9TeZOkoEoAI+34GXg0RVdtBG7PY0o1QrY 19 | WzvsB4hRDTxFIc9sXVUalFTmzXs= 20 | -----END CERTIFICATE REQUEST----- 21 | -------------------------------------------------------------------------------- /11-authentication/x509/client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDah65J0zgQLDaG 3 | HJ6BGHssKOrH87p1lN3brG7PwfytBSMKiQpd0/29/Ha9/1wr6iCMbDX8UrleKSwX 4 | L6tzGCF7SzEr8HXAsphlt3JtBB22KxIpyqTHGkaiZ5ZR5EuQc6gRHX2xAu6CpLUT 5 | Rs5WsmwvZtffFzCz3RCqeT75DHfiveqhlF17ujSoA8VPUsphtg6Waq4XImbnKHDI 6 | +hlPkSKTsVCg8jSvFlm2h8GbfM3AAX+jQsjAjuOwXmjjIIEMln1elU5Er8kn8d4+ 7 | AMvKmNkJXjlGNNwTonU8B6CbGaWYAP33zOxaTaA1Cn2rOebi2r5Nh1gNoowqceC8 8 | fO1aocTZAgMBAAECggEBAJVkulbH6gTMZP3sJMP2e4Yl9tN5INhvS/h4ekzXvih+ 9 | YYU7SHX6jfZK2NZs85Ml/NhixclYuFbR6M11Dk2hiooiTlxOiAGTVrH65mP2s2Ut 10 | Lr6ZRWrD4NP34wDbBHmdR6FjuuC/M1Tmys+B0V/dnC4PrbZawTXFBDa2qsFRr8e2 11 | cA3saic9dIkzPrEmIbLo1/gi3WBOEwSb1DuQel+lW7GvQKJHEwOTeGcy8cSQr3hg 12 | 4+F3+mWdb+bj8v+AoNkpjSusUB+48vGwTOj76vDTOj5DCQNN99eTJsYu5jAkSliS 13 | mDfkt6B13ux05LWXrnaOulBr/PgJjAx+OHg+CJAHp3ECgYEA+W232fslJ0LHtLd2 14 | jinUJ/A4Bdn63oOfQoj6HPwfIlzX0Vw3Zcy3r0evXeVXfqxcIQd1Rg1PchJ8eCV6 15 | /TBVTovfiUs05fHBg3AhiTAY1Cw9BqbyzgMOVdWLaB8tK9/SLgorw2RYs6+G4tnW 16 | YdVyKkUCR7fg1o03XgfD2QRmJk0CgYEA4EmQ2YhjwQlsxU9ujsc6z1wFXDKBwOJM 17 | t5B0DugoKfFRQjw5L8P2nZ5cL8N03/JZWDfpwsc5fiDYmUrrUeBX7wsQQYanLBVJ 18 | bfp5z2yTk8nfSsF0skjyQGKBJ8PUmZkd4J2ioCEAn7DGbBTFRGR50tQGQL+tlaZ+ 19 | tkEPLAPQdr0CgYB6+w7wKjUKY5HF18NbmuIhAv8MW4qm1azbiGARlHnhXneGoXoq 20 | 9kIG6Uhc+mwmZ+NQ4bV/4aYvL1AxiQFX/tHA1ZRUxEEDsyxfmxTd6FoFmv5H3l7P 21 | FpCl35FJuD10aXne+2LShxJ5He1awl9Cg5QzpSzXoaD5CE2pThjRUqru7QKBgQCE 22 | TKC20G8XNPoGQV6Ttg2It10qD1jecB6UwQ7UpDjc1M375g5NkKhuPTVfr0nHt+rf 23 | 0MuA64eMUM+zTLAWceEszjfejxEZPc08pF0p73/100R1kjvF1qWfOPu6exdzKxCm 24 | qBV/ozf8+odwxae/Og1qQUsW8nnwJm/kDehnLDDReQKBgQDZHkCcxB1xMQpESWzE 25 | LqZxk/qu9JDhI4Zt/1kypVWyf+lBPnQgjOeqsZGHnDB0s/u5NTCZ7aCUwcbt1r+f 26 | 0xE+27dIWlWD4vfI0DOLqjsFR1q2U/9Kos2jAJQ35IXM0LlWAembgwlnNprFquhz 27 | kYc7CvrO5ifzJretOGZbRcVHYQ== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /11-authentication/x509/rootCA.srl: -------------------------------------------------------------------------------- 1 | B55F23EC2814992C 2 | -------------------------------------------------------------------------------- /11-authentication/x509/rootCa.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIExTCCA62gAwIBAgIUQtBScgkFMyimWQ0NIWheOxaBpaswDQYJKoZIhvcNAQEL 3 | BQAwgZUxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdC 4 | ZWlqaW5nMRAwDgYDVQQKEwdleGFtcGxlMRAwDgYDVQQLEwdleGFtcGxlMRgwFgYD 5 | VQQDEw93d3cuZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0BCQEWFWxpYW5nLncudEBm 6 | b3htYWlsLmNvbTAeFw0yMjEwMDgxNTA4MTZaFw0yMzEwMDgxNTA4MTZaMIGVMQsw 7 | CQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEQ 8 | MA4GA1UEChMHZXhhbXBsZTEQMA4GA1UECxMHZXhhbXBsZTEYMBYGA1UEAxMPd3d3 9 | LmV4YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFpbC5j 10 | b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSdqFk3Wf3c1qkUMHa 11 | K/sd6RfHfW+LAdkqd/sVI0qP5GxWeu5J3TSj/ciUFUS/czv73crpqgZ09brIFeyZ 12 | 1US/4KBPkIX7UcHdBxPjh4iyUCv20VAbVRDYATirnXBh3VpqR7ohi7q+zJTmjH+4 13 | 7HjJe+suHUXc0r7SlYuqTjZl3VuM8PeGuBf8prHe5Dha2J6cS9fsUHC3Q4X6PUgx 14 | 8FQ1sPxC2CmtBNGvPKQmOq3LSzhICkfQWhSf7Zghv6K5L6FLhSJgwNO4jzfAgvBU 15 | SBOTwZhMGn3ILn5I7IdcRhJpb5KPhykN44ecZZboGu7W6XbWHs21lZfxum0nzXES 16 | GflFAgMBAAGjggEJMIIBBTAdBgNVHQ4EFgQUV+UFrPWR8GI+QntWDcvCTysZinww 17 | gdUGA1UdIwSBzTCByoAUV+UFrPWR8GI+QntWDcvCTysZinyhgZukgZgwgZUxCzAJ 18 | BgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdCZWlqaW5nMRAw 19 | DgYDVQQKEwdleGFtcGxlMRAwDgYDVQQLEwdleGFtcGxlMRgwFgYDVQQDEw93d3cu 20 | ZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0BCQEWFWxpYW5nLncudEBmb3htYWlsLmNv 21 | bYIUQtBScgkFMyimWQ0NIWheOxaBpaswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B 22 | AQsFAAOCAQEALPpoXM9MJz0f6rLdxEkcER0aaRyrGzKdJZUMvOagsVtslOICvd7v 23 | NVwXwwJcberLCi8rRCzQjO57GtqgUG1rE8Q0Da5CM/Aa/xhg/lGYKfIHCSf0hAuq 24 | 2Hi5yF4IMz8zyjF/KZGhsntQbnhxZAy7XrxE+LeniWpFlTDzsteD+sFRSv+f2ZH7 25 | TzsVTnp5GP6cahO3CkUPH1RnlE+4HQUHPqXzRxd9q0GfwKnr0GynsXyAxUfTm5Pb 26 | AEysUFyEjUKMswrPh16X0qIvmWqNctorEPmiNB1+rcMPWwyPffiWA2yMPhYoDx60 27 | Ekeqs4rk7p9IVmMGh4E/bHalI274b+pR8g== 28 | -----END CERTIFICATE----- 29 | -------------------------------------------------------------------------------- /11-authentication/x509/rootCa.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSdqFk3Wf3c1qk 3 | UMHaK/sd6RfHfW+LAdkqd/sVI0qP5GxWeu5J3TSj/ciUFUS/czv73crpqgZ09brI 4 | FeyZ1US/4KBPkIX7UcHdBxPjh4iyUCv20VAbVRDYATirnXBh3VpqR7ohi7q+zJTm 5 | jH+47HjJe+suHUXc0r7SlYuqTjZl3VuM8PeGuBf8prHe5Dha2J6cS9fsUHC3Q4X6 6 | PUgx8FQ1sPxC2CmtBNGvPKQmOq3LSzhICkfQWhSf7Zghv6K5L6FLhSJgwNO4jzfA 7 | gvBUSBOTwZhMGn3ILn5I7IdcRhJpb5KPhykN44ecZZboGu7W6XbWHs21lZfxum0n 8 | zXESGflFAgMBAAECggEAXmk3Fz82/0sw8xsDCvLF0HIa57N+URZALAvsh1vwe8IV 9 | U2oL8PiZP6N90egEkfmIhADHoLBT+y2sX0tuesev8n86itajM81GMPeW1W+cQ5kx 10 | T6Qv0kMDrlJF8L5Mhqo8gAazGY9L84FknlOSjAsQWBoNsv8QsvGbBm5tW7WAM4sb 11 | zk9l1IMYIQmUKXyon9ZeK3ynLpo0bFcYc+gRPWmjIXA/p5Rnl43VnuI0hSRvpkRW 12 | wdC+lFHqd9nUGFhxDznXhRXe5yKQKvWs/gjKhCjnIK3aeL51/9CrBNK8FaVKd+AY 13 | wdOCZD0emVyo052M0RgUeeBAFkf4XM0eMuo1IqCzQQKBgQDuULzKRwGInC6zX4of 14 | Mh3huFRaerZfk70jAxQis0Xpt0a1GA205iD5lpf8yhfOawminihMU3bpgXa0f4PO 15 | wm21+FisszlFkQv7J6wMCeSgqq7zzFPP+3vhIb/ksokkjzPmxoykdj9fp92RJqRt 16 | fDfm2dh0tXDE2UGwo1MbOquJ8QKBgQDiFMpm8olnlv/Xqz2fdHGTNSajBjkLbjCM 17 | DrXzMckojs8ABHMxqpp6xMwoTTqYKFxuNRJ9bvfRARTvlEvs1hHBHnHVrB+d2ZRS 18 | YLGMSkn+V9GKukRO6s/mS0mkTjUPhiVWumh8kONktIbjiltXiujTZItL0jFA8jtJ 19 | HO4dDz2wlQKBgALEazzKEEl+zsgEbv0nvtMVKd2XGTEI7SRP79brT/+Dwk1uBxK3 20 | rWBYkFE+I4KhGY6K2ZrxSSsy9qbn6CbpeQ6o4Ja4ygx1v7bd4hCNuNrowHlSQRLk 21 | L68QjkLgk9kZ1Jd0bMOoH9pDf74kvboLvDZxByNry/BtOWcMrnVdfApxAoGAIbv+ 22 | c5wPGrDyXgkEOe3TIKcWq8665lS707pCNhagsHeWtab0VV3ijR0eZYkYjCnBmQQ8 23 | TREo0zv5FsKnDaDnp0xWqg5z7UbRFfWtqIRRRC1wa+XdWXU6Ll/fji/JRRa8LZPF 24 | EYlBFP7G/d7gQFDO6vQewOKNTOaYKBG0CgwDJX0CgYEA6Ya2nhe4zdAYyad1X08z 25 | IUacHnaW6f0lnybbSEPzhVGJnqdCZdvFF6hjMyp+ABwjgzNaseLTrZAlsXWrOFEp 26 | GcgqhH89H135hlMPNKfvr2gKvV+8FyReeSFT+XhHj8ey79ndHZU7JFejUam2tLpE 27 | EVaQ4PwbPNoB2bBrhRCApAk= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /11-authentication/x509/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEATCCAumgAwIBAgIJALVfI+woFJksMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYD 3 | VQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEQMA4G 4 | A1UEChMHZXhhbXBsZTEQMA4GA1UECxMHZXhhbXBsZTEYMBYGA1UEAxMPd3d3LmV4 5 | YW1wbGUuY29tMSQwIgYJKoZIhvcNAQkBFhVsaWFuZy53LnRAZm94bWFpbC5jb20w 6 | HhcNMjIxMjA0MDkyNzIwWhcNMjMwMTAzMDkyNzIwWjCBgzELMAkGA1UEBhMCQ04x 7 | EDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0JlaWppbmcxEDAOBgNVBAoTB2V4 8 | YW1wbGUxGDAWBgNVBAMTD3d3dy5leGFtcGxlLmNvbTEkMCIGCSqGSIb3DQEJARYV 9 | bGlhbmcudy50QGZveG1haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 10 | CgKCAQEAzlMtteD/T3owzEnTgDhGTh42va4krJQ/7OLJzmuVZELHijml2Wjfdobd 11 | Mb4MQr7sxIeDaGCZ/SKAEoP1qklg35fz6jDRGvP4nkZtoH1aTLOvADnvLqQqWiA/ 12 | /8ZSxv8LxPLrzfUyerIxKciFarPYrhpJ8TSb7wvVpr5Ni54na81KLNt4SaKMKNwn 13 | NnE5/PTwNGiF0/UeO0w87l21g6/QsmztYCH/xeyHe8mLwqbS06vyp94ZKxOQ6qTN 14 | /ciEZyQA2S7Qkw8Zau4N8Yx+W/kx51tCO5ZM18otHHklVpvrYIh+TS/QeQ29r+8Z 15 | zaLzsK9kQGc/Wn2Xt4HQwsFHe1eU0QIDAQABo2QwYjAJBgNVHRMEAjAAMAsGA1Ud 16 | DwQEAwIF4DBIBgNVHREEQTA/gg93d3cuZXhhbXBsZS5jb22CCWxvY2FsaG9zdIIJ 17 | MTI3LjAuMC4xhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBBQUA 18 | A4IBAQBxqJTmexqNW7AGU5yA54WQKZ3RWgbsKKBibaEQkMw44zNfuUFm2ZjOTBTg 19 | qAunXKsH2bkgQcLU+0RvwG6bcFZMcD20o2BHLCXYWLadZQAcLcLlPefDY+7Bmr81 20 | kMGuWS3H5FlF/fp9YT8T21rXomNoJxuJVxn8qcLsrjCW2zwFIi8XOgUQzxYVQtxD 21 | Nm8cGXghbpsBDqJ4D+hGWbdphT4qMqRfbnWQUBfSWRklckO8KBXCowc4ND4MYHfm 22 | tp25cdQ47sYW91uGTdeBzmJjlx952gZAPza6xIPlGRsiQN2xKUPqVS/09scwwyE9 23 | py8r7w9qw7KhMJZNoZty49n0cc6L 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /11-authentication/x509/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIDPDCCAiQCAQAwgYMxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAw 3 | DgYDVQQHEwdCZWlqaW5nMRAwDgYDVQQKEwdleGFtcGxlMRgwFgYDVQQDEw93d3cu 4 | ZXhhbXBsZS5jb20xJDAiBgkqhkiG9w0BCQEWFWxpYW5nLncudEBmb3htYWlsLmNv 5 | bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5TLbXg/096MMxJ04A4 6 | Rk4eNr2uJKyUP+ziyc5rlWRCx4o5pdlo33aG3TG+DEK+7MSHg2hgmf0igBKD9apJ 7 | YN+X8+ow0Rrz+J5GbaB9WkyzrwA57y6kKlogP//GUsb/C8Ty6831MnqyMSnIhWqz 8 | 2K4aSfE0m+8L1aa+TYueJ2vNSizbeEmijCjcJzZxOfz08DRohdP1HjtMPO5dtYOv 9 | 0LJs7WAh/8Xsh3vJi8Km0tOr8qfeGSsTkOqkzf3IhGckANku0JMPGWruDfGMflv5 10 | MedbQjuWTNfKLRx5JVab62CIfk0v0HkNva/vGc2i87CvZEBnP1p9l7eB0MLBR3tX 11 | lNECAwEAAaBzMHEGCSqGSIb3DQEJDjFkMGIwCQYDVR0TBAIwADALBgNVHQ8EBAMC 12 | BeAwSAYDVR0RBEEwP4IPd3d3LmV4YW1wbGUuY29tgglsb2NhbGhvc3SCCTEyNy4w 13 | LjAuMYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEA 14 | FfBCKXmQlyei4APH1jJi/81tBtvrN4Qah5Y0VzvaLiINWijM1grGR6KSRivnAhuZ 15 | laGBDKQbNZobNQCHJj09t6tVZHu2DunxdRC7RyUpRT11oe7M423mjUxTwH3B61uZ 16 | U3qjPg79hfZ9n/WVu6N3OTTShGjnl7XbLT2FEyynfBVyTLZ9/n5Npq+Xr4Ls11Zv 17 | TkqH6zEtbuWa1c2kB/1p3Czn7C5PNbitW10zKxC1oFrfnS60sIarBEhGpVQRvVBm 18 | PTQS3/AkeFVt8IpItzwUBoac8Wuo2UzwJuPFn9YCuWgJUTT1QzAl3A3OX2+7V+7H 19 | vq1jXM+0Ehyhhqfz3HTB3A== 20 | -----END CERTIFICATE REQUEST----- 21 | -------------------------------------------------------------------------------- /11-authentication/x509/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDOUy214P9PejDM 3 | SdOAOEZOHja9riSslD/s4snOa5VkQseKOaXZaN92ht0xvgxCvuzEh4NoYJn9IoAS 4 | g/WqSWDfl/PqMNEa8/ieRm2gfVpMs68AOe8upCpaID//xlLG/wvE8uvN9TJ6sjEp 5 | yIVqs9iuGknxNJvvC9Wmvk2LnidrzUos23hJoowo3Cc2cTn89PA0aIXT9R47TDzu 6 | XbWDr9CybO1gIf/F7Id7yYvCptLTq/Kn3hkrE5DqpM39yIRnJADZLtCTDxlq7g3x 7 | jH5b+THnW0I7lkzXyi0ceSVWm+tgiH5NL9B5Db2v7xnNovOwr2RAZz9afZe3gdDC 8 | wUd7V5TRAgMBAAECggEBALq7yVkdI7UYz+V0w7j+NZMqAT02yPZwzlJlB2SNNg4h 9 | 6lqNxi64nda2RKdqa8pU5hEQ3LuxAm15thQL3mGaO9Thv94rBHWybUdCUqG4Eevt 10 | i+tWg8Tgy3v6SDIDmpOD7XD4srYavu8RKzG3zBhAYVFhdZ6akK6PNXTOM3yzTNZg 11 | uulamJcPS4dGWBR82Z5CdDecvLAI529G9u41zcRDge5vjwWjHWbjgmDy0mHxYivp 12 | u9DJcekBALZobauv6FDVi8Z3xSmECeCp+yiqCQmx7DLFZidzSG5D/Ey+kbicn8Sy 13 | 627avmq+m3/zH9WyZVcxQO/yLSSyn5Yd4JzfP3ujtCkCgYEA+UXRpBe9ULuYBx7K 14 | o6WaV+G8j7SDJaCNFcpJCxVceeGRPIKkXksnYenlZFQVLD71b/fj2YWFFsqFNw0Y 15 | iMFuzIibYI2MuOIkQcMZwlNkJ0ju8oZ5l7OehLE9/qjxwrUcmFnBjsr/kCXhNQqJ 16 | J0OESMCI7CiHM4nY7D9WbZFs+zsCgYEA0+SkDIU2Vgun3NHFPTgqgzekBvyJ/w95 17 | 0c7sMLXhKZfJELf753oGGOecVqVSqY2pNa//fDlth6McBjTdcHGssMel5zCRvG+9 18 | Hi7SpW+gjpuwQALCeAmBITiOrC0bPtKDUP0vIjodPV41ounZVIDj10IVkLQFr6Cx 19 | QzZKdCWed2MCgYEAuqioklrgfbrr3bEWBrL0P4ie/XErn5p46289gRou1GmvqwMc 20 | +CsIw441Iwq/jBFdEsoqiXEtNuLSHGYnEAjg4jINP6DfVnaotcHV4Sk23yADJgLC 21 | vHFZa32Zsb9qweWDEyZrBXVHJ/bljCVmjMtHHH9oSIcUrugzUr0fCA8U748CgYEA 22 | lv8B4GI1fE/GCVf7BEs4EFXgL5JbDEWM+/RG39dcYvVlNOLHQgb0vV6fTCd3ppfq 23 | kvWeTHnoEZYsbEfT3UNEWp2LHhrAX9YIoK+hMH9BnR5ZFORijIPJX1EcapmiJryB 24 | E3+4zN045PhzpGqcktleg5D2KS4AN019xHW1zNrZ+B0CgYEAurkm1+c6XRqaIW6J 25 | 7MH/gqA8R9Tgbe0PrBkJ1oEXSbN252GxU/3bBn14F5HnOBZO3TqPLdLS9+LX4HG0 26 | n5qS7Q3qFFASsqrxaGR/8CkAiqSb7/MJAyjJC+mNs529hikXbQTSucrguFVOGa0x 27 | tMkMUiz+w6zJFq4z4FqjYcikuoA= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /11-authentication/x509/winged-axon-372312-154a8b3aa89d.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "winged-axon-372312", 4 | "private_key_id": "154a8b3aa89d3d4c49826f6dbbbe5542b5a9fbbb", 5 | "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMdhIWlB5e73kK\nAiNM3nlJtF+PjxMZY9VcEpHN0QoAFB/6XE94OtxhDoNIKTMSj6yYB1b8ef+xhPF4\nCJTy19E4RkvMBy1LYLOrnnPo2v0LcJIV9JR+x/hbxLJMJMO3RDAJcjma4S3kcT1l\nxDZQ6QdLSTtwP6h2KZAuBw7WjHTHPqi+KRuGwMv8/zIYG0mNIG0tvccMfPNGe+Q5\nf9ANadorpnYB3Wtz0RAf1V09GKKxsvXuKInY8uhfTDw63W+hhyxroe0zSSs5MFRY\ne0JEUVWfHE5/aC59Su04zuNYbQ3x8/8irXwCMTqbAK4056GA3uBBa8sgsSPB4G0d\nSt3wHWB7AgMBAAECggEAT+FnQrv+u5963g6kxQD8SO/4D8nZr+dBsfWtUkhzzEEQ\nl0teXv48II0/fD9gbUWFrGXdtcliPPRQNNHBg7kOzBomveEl8JeoyomfBmAcUc5a\nvMowA/JTlWLdOAN7FYxF6kLev6RvPhuB3dMRV34bc+36E2pDglrNsjXetbLtYvPk\nw5OLscSCgv893+qmAj2Skb28RKohJj+wiXjqSD4lMVMIlYhB4SKNfd9ia1B1iMi5\nm2Mxuji3WgnJXIfEWPE3HUjzUAWlm/b6IoSyC0b+wekre/STVbTKQksr5HIESD2/\ntYvuo3N79FmabrR4+8cOwilR7UGzv4rxHFzjb61l2QKBgQDpFvhJiRTGTihuPkM8\ndHi3vbipx5c6qBAsiMaVWsWjx6IXvbzRgYPJUL1R0R3XBFGIcBBseEckqTqMalg8\nIrU2n7KLU9+3Bm9GA6dNFlhqdfGDaTmV/9aTzA0+oU6WNTFe3FX7q4d7HWGbQGJZ\nxPjp0br2Iic/Yo7NXHLC9LG12QKBgQDgjr81IV5fgIoeqxyno+eiaGStbL8R39X8\naqgGVyc8LhMEPcUiIO3pfwEV8q1doRH1MAUY0btNEIRNeUEejU6WcYFdnR0uVZy0\n1QbxcgzLdRMVYeDL42Fc7aoZx0/kSmpAieS9WVYdGI222m+oOXnOaUBH6c+dYeLx\nJBTr9bAwcwKBgFRtR32LM4UopihYUQ5Cub8D7zE/5B0Q5trap+NNP601EBc9WHki\nSlPO9OP/tKk/HTEoNiqz3kD/Mv/NPSx6/dxNN+STesLWh9N6W0zmvRvCoLoSkRMt\n2dEq5dk7oDV0Cu/rKxG/bZFAcSxEw9r0J5y5pNimQkUJM+Raig7nhr7xAoGAEZ2B\nCFTux0UZEKDRpaDo6ceQpj4Smv9ZFOz081Jg5IqkuT9zOGMm5pss5aDc0qxw8S/s\nJm9FZx01k7JAVno1QP30bPiHMnxKx7CyU7xjno43igTckoHqwFRwdIc7ECh6P0fR\n5rycUbn8W+y0t5iSoouFHF8OB0WHfO0cqwnh4VsCgYEApz+i8g7afSA6ZSB0fBL3\nlq6zG38mN2Sethb3o1mbkjiAG4pJbjGFhSdP3bbcqrIqLJek2kSWRWJqSoDa81S9\n4LqpMiz26ukjzS+t6ZyPhosi2umGAON9Fa5KoXaFn91EruziiJkZjdqOetKW4A+b\nJ2URfFXP4d5FoCuUGm3e6uc=\n-----END PRIVATE KEY-----\n", 6 | "client_email": "example@winged-axon-372312.iam.gserviceaccount.com", 7 | "client_id": "101800156276712395928", 8 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 9 | "token_uri": "https://oauth2.googleapis.com/token", 10 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 11 | "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/example%40winged-axon-372312.iam.gserviceaccount.com" 12 | } 13 | -------------------------------------------------------------------------------- /12-name_resolver/client/balancer/builder.go: -------------------------------------------------------------------------------- 1 | package balancer 2 | 3 | import ( 4 | "google.golang.org/grpc/balancer" 5 | "google.golang.org/grpc/balancer/base" 6 | ) 7 | 8 | var _ base.PickerBuilder = &Builder{} 9 | 10 | func NewBalancerBuilder() balancer.Builder { 11 | return base.NewBalancerBuilder("random_picker", &Builder{}, base.Config{HealthCheck: true}) 12 | } 13 | 14 | type Builder struct { 15 | } 16 | 17 | func (b *Builder) Build(info base.PickerBuildInfo) balancer.Picker { 18 | if len(info.ReadySCs) == 0 { 19 | return base.NewErrPicker(balancer.ErrNoSubConnAvailable) 20 | } 21 | 22 | var scs []balancer.SubConn 23 | for subConn := range info.ReadySCs { 24 | scs = append(scs, subConn) 25 | } 26 | 27 | return &Picker{ 28 | subConns: scs, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /12-name_resolver/client/balancer/picker.go: -------------------------------------------------------------------------------- 1 | package balancer 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "google.golang.org/grpc/balancer" 7 | ) 8 | 9 | var _ balancer.Picker = &Picker{} 10 | 11 | type Picker struct { 12 | subConns []balancer.SubConn 13 | } 14 | 15 | func (p *Picker) Pick(info balancer.PickInfo) (balancer.PickResult, error) { 16 | index := rand.Intn(len(p.subConns)) 17 | sc := p.subConns[index] 18 | return balancer.PickResult{SubConn: sc}, nil 19 | } -------------------------------------------------------------------------------- /12-name_resolver/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | bl "github.com/liangwt/note/grpc/name_resolver_lb_example/client/balancer" 8 | rs "github.com/liangwt/note/grpc/name_resolver_lb_example/client/resolver" 9 | pb "github.com/liangwt/note/grpc/name_resolver_lb_example/ecommerce" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/balancer" 12 | "google.golang.org/grpc/resolver" 13 | ) 14 | 15 | func main() { 16 | resolver.Register(rs.NewResolverBuilder(map[string][]string{ 17 | "cluster@callee": { 18 | "127.0.0.1:8009", 19 | "127.0.0.1:8010", 20 | }, 21 | })) 22 | 23 | balancer.Register(bl.NewBalancerBuilder()) 24 | 25 | conn, err := grpc.Dial("example:cluster@callee", 26 | grpc.WithInsecure(), 27 | grpc.WithDefaultServiceConfig( 28 | `{"loadBalancingPolicy":"pick_first"}`, 29 | ), 30 | ) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | ctx, cancelFn := context.WithCancel(context.Background()) 36 | defer cancelFn() 37 | 38 | c := pb.NewOrderManagementClient(conn) 39 | 40 | for i := 0; i < 5; i++ { 41 | // Add Order 42 | order := pb.Order{Id: "101", Items: []string{"iPhone XS", "Mac Book Pro"}, Destination: "San Jose, CA", Price: 2300.00} 43 | res, err := c.AddOrder(ctx, &order) 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | log.Printf("Add Orders Res : %s", res) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /12-name_resolver/client/resolver/builder.go: -------------------------------------------------------------------------------- 1 | package resolver 2 | 3 | import "google.golang.org/grpc/resolver" 4 | 5 | var _ resolver.Builder = Builder{} 6 | 7 | type Builder struct { 8 | addrsStore map[string][]string 9 | } 10 | 11 | func NewResolverBuilder(addrsStore map[string][]string) *Builder { 12 | return &Builder{addrsStore: addrsStore} 13 | } 14 | 15 | func (b Builder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { 16 | r := &Resolver{ 17 | target: target, 18 | cc: cc, 19 | addrsStore: b.addrsStore, 20 | } 21 | r.Start() 22 | return r, nil 23 | } 24 | 25 | func (b Builder) Scheme() string { 26 | return "example" 27 | } 28 | -------------------------------------------------------------------------------- /12-name_resolver/client/resolver/resolver.go: -------------------------------------------------------------------------------- 1 | package resolver 2 | 3 | import ( 4 | "google.golang.org/grpc/resolver" 5 | ) 6 | 7 | var _ resolver.Resolver = &Resolver{} 8 | 9 | // impl google.golang.org/grpc/resolver.Resolver 10 | type Resolver struct { 11 | target resolver.Target 12 | cc resolver.ClientConn 13 | 14 | addrsStore map[string][]string 15 | } 16 | 17 | func (r *Resolver) Start() { 18 | // 在静态路由表中查询此 Endpoint 对应 addrs 19 | var addrs []resolver.Address 20 | for _, addr := range r.addrsStore[r.target.URL.Opaque] { 21 | addrs = append(addrs, resolver.Address{Addr: addr}) 22 | } 23 | 24 | r.cc.UpdateState(resolver.State{ 25 | Addresses: addrs, 26 | ServiceConfig: r.cc.ParseServiceConfig(`{"loadBalancingPolicy":"round_robin"}`), 27 | }) 28 | } 29 | 30 | func (r *Resolver) ResolveNow(resolver.ResolveNowOptions) { 31 | 32 | } 33 | 34 | func (r *Resolver) Close() { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /12-name_resolver/ecommerce/order_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.3 5 | // source: pb/order.proto 6 | 7 | package ecommerce 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" 15 | ) 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the grpc package it is being compiled against. 19 | // Requires gRPC-Go v1.32.0 or later. 20 | const _ = grpc.SupportPackageIsVersion7 21 | 22 | // OrderManagementClient is the client API for OrderManagement service. 23 | // 24 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 25 | type OrderManagementClient interface { 26 | AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) 27 | UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) 28 | } 29 | 30 | type orderManagementClient struct { 31 | cc grpc.ClientConnInterface 32 | } 33 | 34 | func NewOrderManagementClient(cc grpc.ClientConnInterface) OrderManagementClient { 35 | return &orderManagementClient{cc} 36 | } 37 | 38 | func (c *orderManagementClient) AddOrder(ctx context.Context, in *Order, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { 39 | out := new(wrapperspb.StringValue) 40 | err := c.cc.Invoke(ctx, "/ecommerce.OrderManagement/addOrder", in, out, opts...) 41 | if err != nil { 42 | return nil, err 43 | } 44 | return out, nil 45 | } 46 | 47 | func (c *orderManagementClient) UpdateOrders(ctx context.Context, opts ...grpc.CallOption) (OrderManagement_UpdateOrdersClient, error) { 48 | stream, err := c.cc.NewStream(ctx, &OrderManagement_ServiceDesc.Streams[0], "/ecommerce.OrderManagement/updateOrders", opts...) 49 | if err != nil { 50 | return nil, err 51 | } 52 | x := &orderManagementUpdateOrdersClient{stream} 53 | return x, nil 54 | } 55 | 56 | type OrderManagement_UpdateOrdersClient interface { 57 | Send(*Order) error 58 | CloseAndRecv() (*wrapperspb.StringValue, error) 59 | grpc.ClientStream 60 | } 61 | 62 | type orderManagementUpdateOrdersClient struct { 63 | grpc.ClientStream 64 | } 65 | 66 | func (x *orderManagementUpdateOrdersClient) Send(m *Order) error { 67 | return x.ClientStream.SendMsg(m) 68 | } 69 | 70 | func (x *orderManagementUpdateOrdersClient) CloseAndRecv() (*wrapperspb.StringValue, error) { 71 | if err := x.ClientStream.CloseSend(); err != nil { 72 | return nil, err 73 | } 74 | m := new(wrapperspb.StringValue) 75 | if err := x.ClientStream.RecvMsg(m); err != nil { 76 | return nil, err 77 | } 78 | return m, nil 79 | } 80 | 81 | // OrderManagementServer is the server API for OrderManagement service. 82 | // All implementations must embed UnimplementedOrderManagementServer 83 | // for forward compatibility 84 | type OrderManagementServer interface { 85 | AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) 86 | UpdateOrders(OrderManagement_UpdateOrdersServer) error 87 | mustEmbedUnimplementedOrderManagementServer() 88 | } 89 | 90 | // UnimplementedOrderManagementServer must be embedded to have forward compatible implementations. 91 | type UnimplementedOrderManagementServer struct { 92 | } 93 | 94 | func (UnimplementedOrderManagementServer) AddOrder(context.Context, *Order) (*wrapperspb.StringValue, error) { 95 | return nil, status.Errorf(codes.Unimplemented, "method AddOrder not implemented") 96 | } 97 | func (UnimplementedOrderManagementServer) UpdateOrders(OrderManagement_UpdateOrdersServer) error { 98 | return status.Errorf(codes.Unimplemented, "method UpdateOrders not implemented") 99 | } 100 | func (UnimplementedOrderManagementServer) mustEmbedUnimplementedOrderManagementServer() {} 101 | 102 | // UnsafeOrderManagementServer may be embedded to opt out of forward compatibility for this service. 103 | // Use of this interface is not recommended, as added methods to OrderManagementServer will 104 | // result in compilation errors. 105 | type UnsafeOrderManagementServer interface { 106 | mustEmbedUnimplementedOrderManagementServer() 107 | } 108 | 109 | func RegisterOrderManagementServer(s grpc.ServiceRegistrar, srv OrderManagementServer) { 110 | s.RegisterService(&OrderManagement_ServiceDesc, srv) 111 | } 112 | 113 | func _OrderManagement_AddOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 114 | in := new(Order) 115 | if err := dec(in); err != nil { 116 | return nil, err 117 | } 118 | if interceptor == nil { 119 | return srv.(OrderManagementServer).AddOrder(ctx, in) 120 | } 121 | info := &grpc.UnaryServerInfo{ 122 | Server: srv, 123 | FullMethod: "/ecommerce.OrderManagement/addOrder", 124 | } 125 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 126 | return srv.(OrderManagementServer).AddOrder(ctx, req.(*Order)) 127 | } 128 | return interceptor(ctx, in, info, handler) 129 | } 130 | 131 | func _OrderManagement_UpdateOrders_Handler(srv interface{}, stream grpc.ServerStream) error { 132 | return srv.(OrderManagementServer).UpdateOrders(&orderManagementUpdateOrdersServer{stream}) 133 | } 134 | 135 | type OrderManagement_UpdateOrdersServer interface { 136 | SendAndClose(*wrapperspb.StringValue) error 137 | Recv() (*Order, error) 138 | grpc.ServerStream 139 | } 140 | 141 | type orderManagementUpdateOrdersServer struct { 142 | grpc.ServerStream 143 | } 144 | 145 | func (x *orderManagementUpdateOrdersServer) SendAndClose(m *wrapperspb.StringValue) error { 146 | return x.ServerStream.SendMsg(m) 147 | } 148 | 149 | func (x *orderManagementUpdateOrdersServer) Recv() (*Order, error) { 150 | m := new(Order) 151 | if err := x.ServerStream.RecvMsg(m); err != nil { 152 | return nil, err 153 | } 154 | return m, nil 155 | } 156 | 157 | // OrderManagement_ServiceDesc is the grpc.ServiceDesc for OrderManagement service. 158 | // It's only intended for direct use with grpc.RegisterService, 159 | // and not to be introspected or modified (even as a copy) 160 | var OrderManagement_ServiceDesc = grpc.ServiceDesc{ 161 | ServiceName: "ecommerce.OrderManagement", 162 | HandlerType: (*OrderManagementServer)(nil), 163 | Methods: []grpc.MethodDesc{ 164 | { 165 | MethodName: "addOrder", 166 | Handler: _OrderManagement_AddOrder_Handler, 167 | }, 168 | }, 169 | Streams: []grpc.StreamDesc{ 170 | { 171 | StreamName: "updateOrders", 172 | Handler: _OrderManagement_UpdateOrders_Handler, 173 | ClientStreams: true, 174 | }, 175 | }, 176 | Metadata: "pb/order.proto", 177 | } 178 | -------------------------------------------------------------------------------- /12-name_resolver/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/name_resolver_lb_example 2 | 3 | go 1.17 4 | 5 | require ( 6 | google.golang.org/grpc v1.44.0 7 | google.golang.org/protobuf v1.27.1 8 | ) 9 | 10 | require ( 11 | cloud.google.com/go v0.34.0 // indirect 12 | github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 14 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect 15 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect 16 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021 // indirect 17 | github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect 18 | github.com/golang/protobuf v1.5.0 // indirect 19 | golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect 20 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect 21 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect 22 | golang.org/x/text v0.3.0 // indirect 23 | google.golang.org/appengine v1.4.0 // indirect 24 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 25 | ) 26 | -------------------------------------------------------------------------------- /12-name_resolver/pb/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | option go_package = "ecommerce/"; 6 | 7 | import "google/protobuf/wrappers.proto"; 8 | 9 | message Order { 10 | string id = 1; 11 | repeated string items = 2; 12 | string description = 3; 13 | float price = 4; 14 | string destination = 5; 15 | } 16 | 17 | service OrderManagement { 18 | rpc addOrder(Order) returns (google.protobuf.StringValue); 19 | rpc updateOrders(stream Order) returns (google.protobuf.StringValue); 20 | } -------------------------------------------------------------------------------- /12-name_resolver/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | pb "github.com/liangwt/note/grpc/name_resolver_lb_example/ecommerce" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | func main() { 11 | s := grpc.NewServer() 12 | pb.RegisterOrderManagementServer(s, &server{}) 13 | 14 | lit, err := net.Listen("tcp", ":8009") 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | if err := s.Serve(lit); err != nil { 20 | panic(err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /12-name_resolver/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | 8 | pb "github.com/liangwt/note/grpc/name_resolver_lb_example/ecommerce" 9 | "google.golang.org/protobuf/types/known/wrapperspb" 10 | ) 11 | 12 | var _ pb.OrderManagementServer = &server{} 13 | 14 | var orders = make(map[string]pb.Order, 0) 15 | 16 | type server struct { 17 | pb.UnimplementedOrderManagementServer 18 | } 19 | 20 | // Simple RPC 21 | func (s *server) AddOrder(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 22 | log.Printf("Order Added. ID : %v", orderReq.Id) 23 | 24 | orders[orderReq.Id] = *orderReq 25 | 26 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 27 | } 28 | 29 | // 在这段程序中,我们对每一个 Recv 都进行了处理 30 | // 当发现 io.EOF (流关闭) 后,需要将最终的响应结果发送给客户端,同时关闭正在另外一侧等待的 Recv 31 | func (s *server) UpdateOrders(stream pb.OrderManagement_UpdateOrdersServer) error { 32 | ordersStr := "Updated Order IDs : " 33 | for { 34 | order, err := stream.Recv() 35 | if err == io.EOF { 36 | // Finished reading the order stream. 37 | return stream.SendAndClose( 38 | &wrapperspb.StringValue{Value: "Orders processed " + ordersStr}) 39 | } 40 | 41 | // Update order 42 | orders[order.Id] = *order 43 | 44 | log.Println("Order ID ", order.Id, ": Updated") 45 | ordersStr += order.Id + ", " 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /12-name_resolver/xds_client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "log" 7 | 8 | pb "github.com/liangwt/note/grpc/name_resolver_lb_example/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/grpc/credentials/insecure" 11 | xdscreds "google.golang.org/grpc/credentials/xds" 12 | 13 | _ "google.golang.org/grpc/xds" // To install the xds resolvers and balancers. 14 | ) 15 | 16 | var ( 17 | xdsCreds = flag.Bool("xds_creds", false, "whether the server should use xDS APIs to receive security configuration") 18 | ) 19 | 20 | func main() { 21 | flag.Parse() 22 | 23 | creds := insecure.NewCredentials() 24 | // xds api也可以传输TLS证书 25 | if *xdsCreds { 26 | log.Println("Using xDS credentials...") 27 | var err error 28 | if creds, err = xdscreds.NewClientCredentials(xdscreds.ClientOptions{FallbackCreds: insecure.NewCredentials()}); err != nil { 29 | panic(err) 30 | } 31 | } 32 | 33 | conn, err := grpc.Dial("xds:///localhost:50051", grpc.WithTransportCredentials(creds)) 34 | if err != nil { 35 | panic(err) 36 | } 37 | 38 | ctx, cancelFn := context.WithCancel(context.Background()) 39 | defer cancelFn() 40 | 41 | c := pb.NewOrderManagementClient(conn) 42 | 43 | for i := 0; i < 5; i++ { 44 | // Add Order 45 | order := pb.Order{Id: "101", Items: []string{"iPhone XS", "Mac Book Pro"}, Destination: "San Jose, CA", Price: 2300.00} 46 | res, err := c.AddOrder(ctx, &order) 47 | if err != nil { 48 | panic(err) 49 | } 50 | 51 | log.Printf("Add Orders Res : %s", res) 52 | } 53 | } -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: ecommerce 5 | opt: 6 | - paths=source_relative 7 | - plugin: go-grpc 8 | out: ecommerce 9 | opt: 10 | - paths=source_relative 11 | - name: grpc-gateway 12 | out: ecommerce 13 | opt: 14 | - paths=source_relative 15 | - generate_unbound_methods=true 16 | - name: openapiv2 17 | out: doc 18 | opt: 19 | - logtostderr=true -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | pb "github.com/liangwt/note/grpc/ecosystem/grpc-gateway/ecommerce" 9 | "google.golang.org/grpc" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("127.0.0.1:8009", grpc.WithInsecure()) 15 | if err != nil { 16 | panic(err) 17 | } 18 | defer conn.Close() 19 | 20 | client := pb.NewOrderManagementClient(conn) 21 | 22 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 23 | defer cancel() 24 | 25 | // Get Order 26 | retrievedOrder, err := client.GetOrder(ctx, &wrapperspb.StringValue{Value: "101"}) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | log.Print("GetOrder Response -> : ", retrievedOrder) 32 | } 33 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/doc/ecommerce/product.swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "ecommerce/product.proto", 5 | "version": "version not set" 6 | }, 7 | "tags": [ 8 | { 9 | "name": "OrderManagementService" 10 | } 11 | ], 12 | "consumes": [ 13 | "application/json" 14 | ], 15 | "produces": [ 16 | "application/json" 17 | ], 18 | "paths": {}, 19 | "definitions": { 20 | "ecommerceOrder": { 21 | "type": "object", 22 | "properties": { 23 | "id": { 24 | "type": "string" 25 | }, 26 | "items": { 27 | "type": "array", 28 | "items": { 29 | "type": "string" 30 | } 31 | }, 32 | "description": { 33 | "type": "string" 34 | }, 35 | "price": { 36 | "type": "number", 37 | "format": "float" 38 | }, 39 | "destination": { 40 | "type": "string" 41 | } 42 | } 43 | }, 44 | "protobufAny": { 45 | "type": "object", 46 | "properties": { 47 | "@type": { 48 | "type": "string" 49 | } 50 | }, 51 | "additionalProperties": {} 52 | }, 53 | "rpcStatus": { 54 | "type": "object", 55 | "properties": { 56 | "code": { 57 | "type": "integer", 58 | "format": "int32" 59 | }, 60 | "message": { 61 | "type": "string" 62 | }, 63 | "details": { 64 | "type": "array", 65 | "items": { 66 | "$ref": "#/definitions/protobufAny" 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/doc/ecommerce/v1/product.swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "ecommerce/v1/product.proto", 5 | "version": "version not set" 6 | }, 7 | "tags": [ 8 | { 9 | "name": "OrderManagementService" 10 | } 11 | ], 12 | "consumes": [ 13 | "application/json" 14 | ], 15 | "produces": [ 16 | "application/json" 17 | ], 18 | "paths": { 19 | "/v1/getOrder": { 20 | "get": { 21 | "operationId": "OrderManagementService_GetOrder", 22 | "responses": { 23 | "200": { 24 | "description": "A successful response.", 25 | "schema": { 26 | "$ref": "#/definitions/v1GetOrderResponse" 27 | } 28 | }, 29 | "default": { 30 | "description": "An unexpected error response.", 31 | "schema": { 32 | "$ref": "#/definitions/rpcStatus" 33 | } 34 | } 35 | }, 36 | "parameters": [ 37 | { 38 | "name": "id", 39 | "in": "query", 40 | "required": false, 41 | "type": "string" 42 | } 43 | ], 44 | "tags": [ 45 | "OrderManagementService" 46 | ] 47 | } 48 | } 49 | }, 50 | "definitions": { 51 | "protobufAny": { 52 | "type": "object", 53 | "properties": { 54 | "@type": { 55 | "type": "string" 56 | } 57 | }, 58 | "additionalProperties": {} 59 | }, 60 | "rpcStatus": { 61 | "type": "object", 62 | "properties": { 63 | "code": { 64 | "type": "integer", 65 | "format": "int32" 66 | }, 67 | "message": { 68 | "type": "string" 69 | }, 70 | "details": { 71 | "type": "array", 72 | "items": { 73 | "$ref": "#/definitions/protobufAny" 74 | } 75 | } 76 | } 77 | }, 78 | "v1GetOrderResponse": { 79 | "type": "object", 80 | "properties": { 81 | "id": { 82 | "type": "string" 83 | }, 84 | "items": { 85 | "type": "array", 86 | "items": { 87 | "type": "string" 88 | } 89 | }, 90 | "description": { 91 | "type": "string" 92 | }, 93 | "price": { 94 | "type": "number", 95 | "format": "float" 96 | }, 97 | "destination": { 98 | "type": "string" 99 | } 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/doc/product.swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "product.proto", 5 | "version": "version not set" 6 | }, 7 | "tags": [ 8 | { 9 | "name": "OrderManagement" 10 | } 11 | ], 12 | "consumes": [ 13 | "application/json" 14 | ], 15 | "produces": [ 16 | "application/json" 17 | ], 18 | "paths": { 19 | "/v1/addOrder": { 20 | "post": { 21 | "operationId": "OrderManagement_addOrder", 22 | "responses": { 23 | "200": { 24 | "description": "A successful response.", 25 | "schema": { 26 | "type": "string" 27 | } 28 | }, 29 | "default": { 30 | "description": "An unexpected error response.", 31 | "schema": { 32 | "$ref": "#/definitions/rpcStatus" 33 | } 34 | } 35 | }, 36 | "parameters": [ 37 | { 38 | "name": "body", 39 | "in": "body", 40 | "required": true, 41 | "schema": { 42 | "$ref": "#/definitions/ecommerceOrder" 43 | } 44 | } 45 | ], 46 | "tags": [ 47 | "OrderManagement" 48 | ] 49 | } 50 | }, 51 | "/v1/getOrder": { 52 | "get": { 53 | "operationId": "OrderManagement_getOrder", 54 | "responses": { 55 | "200": { 56 | "description": "A successful response.", 57 | "schema": { 58 | "$ref": "#/definitions/ecommerceOrder" 59 | } 60 | }, 61 | "default": { 62 | "description": "An unexpected error response.", 63 | "schema": { 64 | "$ref": "#/definitions/rpcStatus" 65 | } 66 | } 67 | }, 68 | "parameters": [ 69 | { 70 | "name": "value", 71 | "description": "The string value.", 72 | "in": "query", 73 | "required": false, 74 | "type": "string" 75 | } 76 | ], 77 | "tags": [ 78 | "OrderManagement" 79 | ] 80 | } 81 | } 82 | }, 83 | "definitions": { 84 | "ecommerceOrder": { 85 | "type": "object", 86 | "properties": { 87 | "id": { 88 | "type": "string" 89 | }, 90 | "items": { 91 | "type": "array", 92 | "items": { 93 | "type": "string" 94 | } 95 | }, 96 | "description": { 97 | "type": "string" 98 | }, 99 | "price": { 100 | "type": "number", 101 | "format": "float" 102 | }, 103 | "destination": { 104 | "type": "string" 105 | } 106 | } 107 | }, 108 | "protobufAny": { 109 | "type": "object", 110 | "properties": { 111 | "@type": { 112 | "type": "string" 113 | } 114 | }, 115 | "additionalProperties": {} 116 | }, 117 | "rpcStatus": { 118 | "type": "object", 119 | "properties": { 120 | "code": { 121 | "type": "integer", 122 | "format": "int32" 123 | }, 124 | "message": { 125 | "type": "string" 126 | }, 127 | "details": { 128 | "type": "array", 129 | "items": { 130 | "$ref": "#/definitions/protobufAny" 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangwt/note/grpc/ecosystem/grpc-gateway 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 7 | google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 8 | google.golang.org/grpc v1.51.0 9 | google.golang.org/protobuf v1.28.1 10 | ) 11 | 12 | require ( 13 | github.com/golang/protobuf v1.5.2 // indirect 14 | golang.org/x/net v0.3.0 // indirect 15 | golang.org/x/sys v0.3.0 // indirect 16 | golang.org/x/text v0.5.0 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= 2 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 3 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 4 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 5 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 6 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 7 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 h1:1JYBfzqrWPcCclBwxFCPAou9n+q86mfnu7NAeHfte7A= 8 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0/go.mod h1:YDZoGHuwE+ov0c8smSH49WLF3F2LaWnYYuDVd+EWrc0= 9 | golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= 10 | golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 11 | golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= 12 | golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 13 | golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= 14 | golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 15 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 16 | google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70= 17 | google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= 18 | google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= 19 | google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= 20 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 21 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 22 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 23 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 24 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/pb/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: googleapis 6 | repository: googleapis 7 | commit: 28151c0d0a1641bf938a7672c500e01d 8 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/pb/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | ## add 9 | deps: 10 | - buf.build/googleapis/googleapis -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/pb/product.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ecommerce; 4 | 5 | import "google/protobuf/wrappers.proto"; 6 | import "google/api/annotations.proto"; 7 | 8 | option go_package = "/ecommerce"; 9 | 10 | service OrderManagement { 11 | rpc getOrder(google.protobuf.StringValue) returns (Order) { 12 | option (google.api.http) = { 13 | get : "/v1/getOrder" 14 | }; 15 | } 16 | 17 | rpc addOrder1(Order) returns (google.protobuf.StringValue) { 18 | option (google.api.http) = { 19 | post : "/v1/addOrder1" 20 | body : "*" 21 | }; 22 | } 23 | 24 | rpc addOrder2(OrderRequest) returns (google.protobuf.StringValue) { 25 | option (google.api.http) = { 26 | post : "/v1/addOrder2" 27 | body : "order" 28 | }; 29 | } 30 | } 31 | 32 | message OrderRequest { 33 | Order order = 1; 34 | } 35 | 36 | message Order { 37 | string id = 1; 38 | repeated string items = 2; 39 | string description = 3; 40 | float price = 4; 41 | google.protobuf.StringValue destination = 5; 42 | } -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "net/http" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | pb "github.com/liangwt/note/grpc/ecosystem/grpc-gateway/ecommerce" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | // curl -s -X POST \ 14 | // '127.0.0.1:8010/v1/addOrder' \ 15 | // --header 'Accept: */*' \ 16 | // --data '{"id": "102","items": ["Google","Baidu"],"description": "example","price": 0,"destination": "example"}' 17 | 18 | func main() { 19 | grpcPort, gwPort := ":8009", ":8010" 20 | 21 | go func() { 22 | lis, err := net.Listen("tcp", grpcPort) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | s := grpc.NewServer() 28 | 29 | pb.RegisterOrderManagementServer(s, &OrderManagementImpl{}) 30 | if err := s.Serve(lis); err != nil { 31 | panic(err) 32 | } 33 | }() 34 | 35 | // 建立一个到gRPC Port的连接 36 | conn, err := grpc.DialContext( 37 | context.Background(), 38 | "127.0.0.1"+grpcPort, 39 | grpc.WithBlock(), 40 | grpc.WithInsecure(), 41 | ) 42 | if err != nil { 43 | panic(err) 44 | } 45 | 46 | gwmux := runtime.NewServeMux() 47 | err = pb.RegisterOrderManagementHandler(context.Background(), gwmux, conn) 48 | if err != nil { 49 | panic(err) 50 | } 51 | 52 | err = gwmux.HandlePath("GET", "/hello/{name}", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) { 53 | w.Write([]byte("hello " + pathParams["name"])) 54 | }) 55 | 56 | http.ListenAndServe(gwPort, gwmux) 57 | 58 | // 以下和http.ListenAndServe(gwPort, gwmux)等价 59 | 60 | // gwServer := &http.Server{ 61 | // Addr: gwPort, 62 | // Handler: gwmux, 63 | // } 64 | 65 | // if err := gwServer.ListenAndServe(); err != nil { 66 | // panic(err) 67 | // } 68 | } 69 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/server/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/ecosystem/grpc-gateway/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 14 | 15 | var orders = map[string]pb.Order{ 16 | "101": { 17 | Id: "101", 18 | Items: []string{ 19 | "Google", 20 | "Baidu", 21 | }, 22 | Description: "example", 23 | Price: 0, 24 | Destination: &wrapperspb.StringValue{ 25 | Value: "example", 26 | }, 27 | }, 28 | } 29 | 30 | type OrderManagementImpl struct { 31 | pb.UnimplementedOrderManagementServer 32 | } 33 | 34 | func (s *OrderManagementImpl) AddOrder2(ctx context.Context, orderReq *pb.OrderRequest) (*wrapperspb.StringValue, error) { 35 | log.Printf("Order Added. ID : %v", orderReq.Order.Id) 36 | orders[orderReq.Order.Id] = *orderReq.Order 37 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Order.Id}, nil 38 | } 39 | 40 | // Simple RPC 41 | func (s *OrderManagementImpl) AddOrder1(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 42 | log.Printf("Order Added. ID : %v", orderReq.Id) 43 | orders[orderReq.Id] = *orderReq 44 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 45 | } 46 | 47 | // Simple RPC 48 | func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 49 | ord, exists := orders[orderId.Value] 50 | if exists { 51 | return &ord, status.New(codes.OK, "").Err() 52 | } 53 | 54 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 55 | } 56 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/server2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 8 | pb "github.com/liangwt/note/grpc/ecosystem/grpc-gateway/ecommerce" 9 | ) 10 | 11 | func main() { 12 | gwmux := runtime.NewServeMux() 13 | 14 | err := pb.RegisterOrderManagementHandlerServer(context.Background(), gwmux, &OrderManagementImpl{}) 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | err = gwmux.HandlePath("GET", "/hello/{name}", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) { 20 | w.Write([]byte("hello " + pathParams["name"])) 21 | }) 22 | 23 | http.ListenAndServe(":8010", gwmux) 24 | } 25 | -------------------------------------------------------------------------------- /13-ecosystem/grpc-gateway/server2/order.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | pb "github.com/liangwt/note/grpc/ecosystem/grpc-gateway/ecommerce" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "google.golang.org/protobuf/types/known/wrapperspb" 11 | ) 12 | 13 | var _ pb.OrderManagementServer = &OrderManagementImpl{} 14 | 15 | var orders = map[string]pb.Order{ 16 | "101": { 17 | Id: "101", 18 | Items: []string{ 19 | "Google", 20 | "Baidu", 21 | }, 22 | Description: "example", 23 | Price: 0, 24 | Destination: &wrapperspb.StringValue{ 25 | Value: "example", 26 | }, 27 | }, 28 | } 29 | 30 | type OrderManagementImpl struct { 31 | pb.UnimplementedOrderManagementServer 32 | } 33 | 34 | func (s *OrderManagementImpl) AddOrder2(ctx context.Context, orderReq *pb.OrderRequest) (*wrapperspb.StringValue, error) { 35 | log.Printf("Order Added. ID : %v", orderReq.Order.Id) 36 | orders[orderReq.Order.Id] = *orderReq.Order 37 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Order.Id}, nil 38 | } 39 | 40 | // Simple RPC 41 | func (s *OrderManagementImpl) AddOrder1(ctx context.Context, orderReq *pb.Order) (*wrapperspb.StringValue, error) { 42 | log.Printf("Order Added. ID : %v", orderReq.Id) 43 | orders[orderReq.Id] = *orderReq 44 | return &wrapperspb.StringValue{Value: "Order Added: " + orderReq.Id}, nil 45 | } 46 | 47 | // Simple RPC 48 | func (s *OrderManagementImpl) GetOrder(ctx context.Context, orderId *wrapperspb.StringValue) (*pb.Order, error) { 49 | ord, exists := orders[orderId.Value] 50 | if exists { 51 | return &ord, status.New(codes.OK, "").Err() 52 | } 53 | 54 | return nil, status.Errorf(codes.NotFound, "Order does not exist. : ", orderId) 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 写给go开发者的gRPC教程示例代码 2 | 3 | 写给go开发者的gRPC教程系列教程: 4 | 5 | 👉 [点击去掘金查看](https://juejin.cn/column/7191008828509388860) 6 | 7 | 👉 [点击去微信公众号查看](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzIyMTI4OTY3Mw==&action=getalbum&album_id=2760500493343014914#wechat_redirect) 8 | 9 | 10 | 11 | ![weixin](weixin.png) 12 | -------------------------------------------------------------------------------- /weixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangwt/grpc-example/dc6ce158430eac918f26114262942f26abab806f/weixin.png --------------------------------------------------------------------------------