From ec7a77f3ca8ac26b23d864e7653dc4db4e479447 Mon Sep 17 00:00:00 2001 From: "sanskarsharma3110@gmail.com" Date: Wed, 24 Jul 2024 01:50:18 +0530 Subject: [PATCH] feat: grpc application server Signed-off-by: sanskarsharma3110@gmail.com --- grpc/client/client.go | 45 ++++ grpc/generated/proto/message.pb.go | 239 ++++++++++++++++++ grpc/generated/proto/message_grpc.pb.go | 318 ++++++++++++++++++++++++ grpc/go.mod | 15 ++ grpc/go.sum | 14 ++ grpc/main.go | 8 + grpc/proto/message.proto | 19 ++ grpc/server/server.go | 75 ++++++ 8 files changed, 733 insertions(+) create mode 100644 grpc/client/client.go create mode 100644 grpc/generated/proto/message.pb.go create mode 100644 grpc/generated/proto/message_grpc.pb.go create mode 100644 grpc/go.mod create mode 100644 grpc/go.sum create mode 100644 grpc/main.go create mode 100644 grpc/proto/message.proto create mode 100644 grpc/server/server.go diff --git a/grpc/client/client.go b/grpc/client/client.go new file mode 100644 index 0000000..a133620 --- /dev/null +++ b/grpc/client/client.go @@ -0,0 +1,45 @@ +package client + +import ( + "context" + "io" + "log" + "time" + + pb "github.com/keploy/samples-go/grpc/generated/proto" + "google.golang.org/grpc" +) + +const ( + address = "localhost:50051" +) + +func StartClient() { + conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) + if err != nil { + log.Fatalf("did not connect: %v", err) + } + defer conn.Close() + + client := pb.NewStudentServiceClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + stream, err := client.GetStudentStream(ctx, &pb.StudentRequest{Id: 1}) + if err != nil { + log.Fatalf("could not get student stream: %v", err) + } + + for { + msg, err := stream.Recv() + if err == io.EOF { + log.Println("Stream closed") + break + } + if err != nil { + log.Fatalf("stream receive error: %v", err) + } + log.Printf("Streamed Student: Name: %s, Age: %d", msg.GetName(), msg.GetAge()) + } +} diff --git a/grpc/generated/proto/message.pb.go b/grpc/generated/proto/message.pb.go new file mode 100644 index 0000000..f2644a9 --- /dev/null +++ b/grpc/generated/proto/message.pb.go @@ -0,0 +1,239 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v3.21.12 +// source: proto/message.proto + +package generated + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type StudentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *StudentRequest) Reset() { + *x = StudentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_message_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StudentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StudentRequest) ProtoMessage() {} + +func (x *StudentRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_message_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StudentRequest.ProtoReflect.Descriptor instead. +func (*StudentRequest) Descriptor() ([]byte, []int) { + return file_proto_message_proto_rawDescGZIP(), []int{0} +} + +func (x *StudentRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type StudentResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Age int32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` +} + +func (x *StudentResponse) Reset() { + *x = StudentResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_message_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StudentResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StudentResponse) ProtoMessage() {} + +func (x *StudentResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_message_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StudentResponse.ProtoReflect.Descriptor instead. +func (*StudentResponse) Descriptor() ([]byte, []int) { + return file_proto_message_proto_rawDescGZIP(), []int{1} +} + +func (x *StudentResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *StudentResponse) GetAge() int32 { + if x != nil { + return x.Age + } + return 0 +} + +var File_proto_message_proto protoreflect.FileDescriptor + +var file_proto_message_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x20, 0x0a, 0x0e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x37, 0x0a, 0x0f, 0x53, 0x74, 0x75, 0x64, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x67, 0x65, + 0x32, 0xfe, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, + 0x74, 0x12, 0x0f, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, + 0x64, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x0f, 0x2e, 0x53, 0x74, 0x75, + 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x53, 0x74, + 0x75, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, + 0x01, 0x12, 0x3a, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x0f, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x42, 0x0a, + 0x17, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, + 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x0f, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x53, 0x74, 0x75, 0x64, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, + 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6b, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2d, 0x67, + 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_message_proto_rawDescOnce sync.Once + file_proto_message_proto_rawDescData = file_proto_message_proto_rawDesc +) + +func file_proto_message_proto_rawDescGZIP() []byte { + file_proto_message_proto_rawDescOnce.Do(func() { + file_proto_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_message_proto_rawDescData) + }) + return file_proto_message_proto_rawDescData +} + +var file_proto_message_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_message_proto_goTypes = []any{ + (*StudentRequest)(nil), // 0: StudentRequest + (*StudentResponse)(nil), // 1: StudentResponse +} +var file_proto_message_proto_depIdxs = []int32{ + 0, // 0: StudentService.GetStudent:input_type -> StudentRequest + 0, // 1: StudentService.GetStudentStream:input_type -> StudentRequest + 0, // 2: StudentService.SendStudentStream:input_type -> StudentRequest + 0, // 3: StudentService.SendAndGetStudentStream:input_type -> StudentRequest + 1, // 4: StudentService.GetStudent:output_type -> StudentResponse + 1, // 5: StudentService.GetStudentStream:output_type -> StudentResponse + 1, // 6: StudentService.SendStudentStream:output_type -> StudentResponse + 1, // 7: StudentService.SendAndGetStudentStream:output_type -> StudentResponse + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_proto_message_proto_init() } +func file_proto_message_proto_init() { + if File_proto_message_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_message_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*StudentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_message_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*StudentResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_message_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_message_proto_goTypes, + DependencyIndexes: file_proto_message_proto_depIdxs, + MessageInfos: file_proto_message_proto_msgTypes, + }.Build() + File_proto_message_proto = out.File + file_proto_message_proto_rawDesc = nil + file_proto_message_proto_goTypes = nil + file_proto_message_proto_depIdxs = nil +} diff --git a/grpc/generated/proto/message_grpc.pb.go b/grpc/generated/proto/message_grpc.pb.go new file mode 100644 index 0000000..cacdff0 --- /dev/null +++ b/grpc/generated/proto/message_grpc.pb.go @@ -0,0 +1,318 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.4.0 +// - protoc v3.21.12 +// source: proto/message.proto + +package generated + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.62.0 or later. +const _ = grpc.SupportPackageIsVersion8 + +const ( + StudentService_GetStudent_FullMethodName = "/StudentService/GetStudent" + StudentService_GetStudentStream_FullMethodName = "/StudentService/GetStudentStream" + StudentService_SendStudentStream_FullMethodName = "/StudentService/SendStudentStream" + StudentService_SendAndGetStudentStream_FullMethodName = "/StudentService/SendAndGetStudentStream" +) + +// StudentServiceClient is the client API for StudentService service. +// +// 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. +type StudentServiceClient interface { + GetStudent(ctx context.Context, in *StudentRequest, opts ...grpc.CallOption) (*StudentResponse, error) + GetStudentStream(ctx context.Context, in *StudentRequest, opts ...grpc.CallOption) (StudentService_GetStudentStreamClient, error) + SendStudentStream(ctx context.Context, opts ...grpc.CallOption) (StudentService_SendStudentStreamClient, error) + SendAndGetStudentStream(ctx context.Context, opts ...grpc.CallOption) (StudentService_SendAndGetStudentStreamClient, error) +} + +type studentServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewStudentServiceClient(cc grpc.ClientConnInterface) StudentServiceClient { + return &studentServiceClient{cc} +} + +func (c *studentServiceClient) GetStudent(ctx context.Context, in *StudentRequest, opts ...grpc.CallOption) (*StudentResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(StudentResponse) + err := c.cc.Invoke(ctx, StudentService_GetStudent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *studentServiceClient) GetStudentStream(ctx context.Context, in *StudentRequest, opts ...grpc.CallOption) (StudentService_GetStudentStreamClient, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &StudentService_ServiceDesc.Streams[0], StudentService_GetStudentStream_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &studentServiceGetStudentStreamClient{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type StudentService_GetStudentStreamClient interface { + Recv() (*StudentResponse, error) + grpc.ClientStream +} + +type studentServiceGetStudentStreamClient struct { + grpc.ClientStream +} + +func (x *studentServiceGetStudentStreamClient) Recv() (*StudentResponse, error) { + m := new(StudentResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *studentServiceClient) SendStudentStream(ctx context.Context, opts ...grpc.CallOption) (StudentService_SendStudentStreamClient, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &StudentService_ServiceDesc.Streams[1], StudentService_SendStudentStream_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &studentServiceSendStudentStreamClient{ClientStream: stream} + return x, nil +} + +type StudentService_SendStudentStreamClient interface { + Send(*StudentRequest) error + CloseAndRecv() (*StudentResponse, error) + grpc.ClientStream +} + +type studentServiceSendStudentStreamClient struct { + grpc.ClientStream +} + +func (x *studentServiceSendStudentStreamClient) Send(m *StudentRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *studentServiceSendStudentStreamClient) CloseAndRecv() (*StudentResponse, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(StudentResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *studentServiceClient) SendAndGetStudentStream(ctx context.Context, opts ...grpc.CallOption) (StudentService_SendAndGetStudentStreamClient, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &StudentService_ServiceDesc.Streams[2], StudentService_SendAndGetStudentStream_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &studentServiceSendAndGetStudentStreamClient{ClientStream: stream} + return x, nil +} + +type StudentService_SendAndGetStudentStreamClient interface { + Send(*StudentRequest) error + Recv() (*StudentResponse, error) + grpc.ClientStream +} + +type studentServiceSendAndGetStudentStreamClient struct { + grpc.ClientStream +} + +func (x *studentServiceSendAndGetStudentStreamClient) Send(m *StudentRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *studentServiceSendAndGetStudentStreamClient) Recv() (*StudentResponse, error) { + m := new(StudentResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// StudentServiceServer is the server API for StudentService service. +// All implementations must embed UnimplementedStudentServiceServer +// for forward compatibility +type StudentServiceServer interface { + GetStudent(context.Context, *StudentRequest) (*StudentResponse, error) + GetStudentStream(*StudentRequest, StudentService_GetStudentStreamServer) error + SendStudentStream(StudentService_SendStudentStreamServer) error + SendAndGetStudentStream(StudentService_SendAndGetStudentStreamServer) error + mustEmbedUnimplementedStudentServiceServer() +} + +// UnimplementedStudentServiceServer must be embedded to have forward compatible implementations. +type UnimplementedStudentServiceServer struct { +} + +func (UnimplementedStudentServiceServer) GetStudent(context.Context, *StudentRequest) (*StudentResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStudent not implemented") +} +func (UnimplementedStudentServiceServer) GetStudentStream(*StudentRequest, StudentService_GetStudentStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetStudentStream not implemented") +} +func (UnimplementedStudentServiceServer) SendStudentStream(StudentService_SendStudentStreamServer) error { + return status.Errorf(codes.Unimplemented, "method SendStudentStream not implemented") +} +func (UnimplementedStudentServiceServer) SendAndGetStudentStream(StudentService_SendAndGetStudentStreamServer) error { + return status.Errorf(codes.Unimplemented, "method SendAndGetStudentStream not implemented") +} +func (UnimplementedStudentServiceServer) mustEmbedUnimplementedStudentServiceServer() {} + +// UnsafeStudentServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to StudentServiceServer will +// result in compilation errors. +type UnsafeStudentServiceServer interface { + mustEmbedUnimplementedStudentServiceServer() +} + +func RegisterStudentServiceServer(s grpc.ServiceRegistrar, srv StudentServiceServer) { + s.RegisterService(&StudentService_ServiceDesc, srv) +} + +func _StudentService_GetStudent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StudentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StudentServiceServer).GetStudent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StudentService_GetStudent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StudentServiceServer).GetStudent(ctx, req.(*StudentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StudentService_GetStudentStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(StudentRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(StudentServiceServer).GetStudentStream(m, &studentServiceGetStudentStreamServer{ServerStream: stream}) +} + +type StudentService_GetStudentStreamServer interface { + Send(*StudentResponse) error + grpc.ServerStream +} + +type studentServiceGetStudentStreamServer struct { + grpc.ServerStream +} + +func (x *studentServiceGetStudentStreamServer) Send(m *StudentResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _StudentService_SendStudentStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(StudentServiceServer).SendStudentStream(&studentServiceSendStudentStreamServer{ServerStream: stream}) +} + +type StudentService_SendStudentStreamServer interface { + SendAndClose(*StudentResponse) error + Recv() (*StudentRequest, error) + grpc.ServerStream +} + +type studentServiceSendStudentStreamServer struct { + grpc.ServerStream +} + +func (x *studentServiceSendStudentStreamServer) SendAndClose(m *StudentResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *studentServiceSendStudentStreamServer) Recv() (*StudentRequest, error) { + m := new(StudentRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _StudentService_SendAndGetStudentStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(StudentServiceServer).SendAndGetStudentStream(&studentServiceSendAndGetStudentStreamServer{ServerStream: stream}) +} + +type StudentService_SendAndGetStudentStreamServer interface { + Send(*StudentResponse) error + Recv() (*StudentRequest, error) + grpc.ServerStream +} + +type studentServiceSendAndGetStudentStreamServer struct { + grpc.ServerStream +} + +func (x *studentServiceSendAndGetStudentStreamServer) Send(m *StudentResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *studentServiceSendAndGetStudentStreamServer) Recv() (*StudentRequest, error) { + m := new(StudentRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// StudentService_ServiceDesc is the grpc.ServiceDesc for StudentService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var StudentService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "StudentService", + HandlerType: (*StudentServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetStudent", + Handler: _StudentService_GetStudent_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetStudentStream", + Handler: _StudentService_GetStudentStream_Handler, + ServerStreams: true, + }, + { + StreamName: "SendStudentStream", + Handler: _StudentService_SendStudentStream_Handler, + ClientStreams: true, + }, + { + StreamName: "SendAndGetStudentStream", + Handler: _StudentService_SendAndGetStudentStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "proto/message.proto", +} diff --git a/grpc/go.mod b/grpc/go.mod new file mode 100644 index 0000000..8a0c3b2 --- /dev/null +++ b/grpc/go.mod @@ -0,0 +1,15 @@ +module github.com/keploy/samples-go/grpc + +go 1.22.2 + +require ( + google.golang.org/grpc v1.65.0 + google.golang.org/protobuf v1.34.1 +) + +require ( + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect +) diff --git a/grpc/go.sum b/grpc/go.sum new file mode 100644 index 0000000..11fe2ff --- /dev/null +++ b/grpc/go.sum @@ -0,0 +1,14 @@ +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/grpc/main.go b/grpc/main.go new file mode 100644 index 0000000..1b89dc8 --- /dev/null +++ b/grpc/main.go @@ -0,0 +1,8 @@ +package main + +import "github.com/keploy/samples-go/grpc/server" + +func main() { + server.StartServer() + +} diff --git a/grpc/proto/message.proto b/grpc/proto/message.proto new file mode 100644 index 0000000..760ecba --- /dev/null +++ b/grpc/proto/message.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option go_package = "github.com/keploy/samples-go/grpc/generated"; + +service StudentService { + rpc GetStudent(StudentRequest) returns (StudentResponse) {}; + rpc GetStudentStream(StudentRequest) returns (stream StudentResponse) {}; + rpc SendStudentStream(stream StudentRequest) returns (StudentResponse) {}; + rpc SendAndGetStudentStream(stream StudentRequest) returns (stream StudentResponse) {} +} + +message StudentRequest { + int32 id = 1; +} + +message StudentResponse { + string name = 1; + int32 age = 2; +} diff --git a/grpc/server/server.go b/grpc/server/server.go new file mode 100644 index 0000000..4e9b2d4 --- /dev/null +++ b/grpc/server/server.go @@ -0,0 +1,75 @@ +package server + +import ( + "context" + "io" + "log" + "net" + + pb "github.com/keploy/samples-go/grpc/generated/proto" + "google.golang.org/grpc" +) + +type server struct { + pb.UnimplementedStudentServiceServer +} + +func (s *server) GetStudent(ctx context.Context, req *pb.StudentRequest) (*pb.StudentResponse, error) { + log.Printf("Received: %v", req.GetId()) + return &pb.StudentResponse{Name: "John Doe", Age: 21}, nil +} + +func (s *server) GetStudentStream(req *pb.StudentRequest, stream pb.StudentService_GetStudentStreamServer) error { + // For simplicity, just sending a static response. + err := stream.Send(&pb.StudentResponse{Name: "John Doe", Age: 21}) + if err != nil { + return err + } + return nil +} + +func (s *server) SendStudentStream(stream pb.StudentService_SendStudentStreamServer) error { + var student *pb.StudentRequest + for { + req, err := stream.Recv() + if err == io.EOF { + return stream.SendAndClose(&pb.StudentResponse{Name: "Received all requests", Age: 0}) + } + if err != nil { + return err + } + student = req + log.Printf("Received: %v", student.GetId()) + } +} + +func (s *server) SendAndGetStudentStream(stream pb.StudentService_SendAndGetStudentStreamServer) error { + for { + req, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + log.Printf("Received: %v", req.GetId()) + if err := stream.Send(&pb.StudentResponse{Name: "John Doe", Age: 21}); err != nil { + return err + } + } +} + +func StartServer() { + lis, err := net.Listen("tcp", ":50051") + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + s := grpc.NewServer() + pb.RegisterStudentServiceServer(s, &server{}) + + log.Printf("Server listening at %v", lis.Addr()) + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } +}