gf/contrib/rpc/grpcx/grpcx_interceptor_server.go

104 lines
3.8 KiB
Go

// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package grpcx
import (
"context"
"google.golang.org/protobuf/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/gogf/gf/contrib/rpc/grpcx/v2/internal/tracing"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gutil"
)
// ChainUnary returns a ServerOption that specifies the chained interceptor
// for unary RPCs. The first interceptor will be the outermost,
// while the last interceptor will be the innermost wrapper around the real call.
// All unary interceptors added by this method will be chained.
func (s modServer) ChainUnary(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption {
return grpc.ChainUnaryInterceptor(interceptors...)
}
// ChainStream returns a ServerOption that specifies the chained interceptor
// for stream RPCs. The first interceptor will be the outermost,
// while the last interceptor will be the innermost wrapper around the real call.
// All stream interceptors added by this method will be chained.
func (s modServer) ChainStream(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption {
return grpc.ChainStreamInterceptor(interceptors...)
}
// UnaryError is the default unary interceptor for error converting from custom error to grpc error.
func (s modServer) UnaryError(
ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (interface{}, error) {
res, err := handler(ctx, req)
if err != nil {
code := gerror.Code(err)
if code.Code() != -1 {
err = status.Error(codes.Code(code.Code()), err.Error())
}
}
return res, err
}
// UnaryRecover is the first interceptor that keep server not down from panics.
func (s modServer) UnaryRecover(
ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (res interface{}, err error) {
gutil.TryCatch(ctx, func(ctx2 context.Context) {
res, err = handler(ctx, req)
}, func(ctx context.Context, exception error) {
err = gerror.WrapCode(gcode.New(int(codes.Internal), "", nil), exception, "panic recovered")
})
return
}
// UnaryValidate Common validation unary interpreter.
func (s modServer) UnaryValidate(
ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (interface{}, error) {
// It does nothing if there's no validation tag in the struct definition.
if err := g.Validator().Data(req).Run(ctx); err != nil {
return nil, gerror.NewCode(
gcode.New(int(codes.InvalidArgument), "", nil),
gerror.Current(err).Error(),
)
}
return handler(ctx, req)
}
func (s modServer) UnaryAllowNilRes(
ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (interface{}, error) {
res, err := handler(ctx, req)
if g.IsNil(res) {
res = proto.Message(nil)
}
return res, err
}
// UnaryTracing is a unary interceptor for adding tracing feature for gRPC server using OpenTelemetry.
// The tracing feature is builtin enabled.
func (s modServer) UnaryTracing(
ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (interface{}, error) {
return tracing.UnaryServerInterceptor(ctx, req, info, handler)
}
// StreamTracing is a stream unary interceptor for adding tracing feature for gRPC server using OpenTelemetry.
func (s modServer) StreamTracing(
srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler,
) error {
return tracing.StreamServerInterceptor(srv, ss, info, handler)
}