grpc-demo/internal/greeter/server.go

108 lines
2.5 KiB
Go

package greeter
import (
"context"
"errors"
"fmt"
"io"
"gitea.dwysokinski.me/Kichiyaki/grpc-demo/proto"
"go.uber.org/zap"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
type Server struct {
proto.UnimplementedGreeterServer
logger *zap.Logger
}
func NewServer(logger *zap.Logger) *Server {
return &Server{logger: logger}
}
func (s *Server) SayHello(ctx context.Context, r *proto.HelloRequest) (*proto.HelloReply, error) {
md, ok := metadata.FromIncomingContext(ctx)
if ok {
s.logger.Debug("received metadata", zap.Any("metadata", md))
}
return &proto.HelloReply{
Message: buildHelloMsg(r.GetName()),
}, nil
}
func (s *Server) SayHelloToJames(_ context.Context, r *proto.HelloRequest) (*proto.HelloReply, error) {
name := r.GetName()
if name != "James" {
st, err := status.
New(codes.InvalidArgument, "invalid name").
WithDetails(&errdetails.BadRequest{
FieldViolations: []*errdetails.BadRequest_FieldViolation{
{
Field: "name",
Description: "must be James",
},
},
})
if err != nil {
return nil, status.New(codes.Internal, "internal server error").Err()
}
return nil, st.Err()
}
return &proto.HelloReply{
Message: buildHelloMsg(name),
}, nil
}
func (s *Server) SayHelloServerStream(r *proto.MultiHelloRequest, stream proto.Greeter_SayHelloServerStreamServer) error {
for _, n := range r.GetNames() {
if err := stream.Send(&proto.HelloReply{
Message: buildHelloMsg(n),
}); err != nil {
return err
}
}
return nil
}
func (s *Server) SayHelloClientStream(stream proto.Greeter_SayHelloClientStreamServer) error {
var messages []string
for {
r, err := stream.Recv()
if errors.Is(err, io.EOF) {
return stream.SendAndClose(&proto.MultiHelloReply{
Messages: messages,
})
}
if err != nil {
return fmt.Errorf("stream returned error: %w", err)
}
messages = append(messages, buildHelloMsg(r.GetName()))
}
}
func (s *Server) SayHelloBidirectionalStream(stream proto.Greeter_SayHelloBidirectionalStreamServer) error {
for {
r, err := stream.Recv()
if errors.Is(err, io.EOF) {
return nil
}
if err != nil {
return fmt.Errorf("stream returned error: %w", err)
}
if err = stream.Send(&proto.HelloReply{Message: buildHelloMsg(r.GetName())}); err != nil {
return fmt.Errorf("couldn't send reply: %w", err)
}
}
}
func buildHelloMsg(name string) string {
return "Hello " + name + "!"
}