var _ pb.HelloServiceServer = new(HelloServiceServer)
// UnimplementedHelloServiceServer must be embedded to have forward compatible implementations. type HelloServiceServer struct { *pb.UnimplementedHelloServiceServer }
// 客户端的Channel方法返回一个HelloService_ChannelClient类型的返回值,可以用于和服务端进行双向通信 // HelloServiceClient is the client API for HelloService 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 HelloServiceClient interface { Hello(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) Channel(ctx context.Context, opts ...grpc.CallOption) (HelloService_ChannelClient, error) }
// 在服务端的Channel方法参数是一个新的HelloService_ChannelServer类型的参数,可以用于和客户端双向通信 // HelloServiceServer is the server API for HelloService service. // All implementations must embed UnimplementedHelloServiceServer // for forward compatibility type HelloServiceServer interface { Hello(context.Context, *Request) (*Response, error) Channel(HelloService_ChannelServer) error mustEmbedUnimplementedHelloServiceServer() }
// GrpcAuthUnaryServerInterceptor returns a new unary server interceptor for auth. funcGrpcAuthUnaryServerInterceptor() grpc.UnaryServerInterceptor { return newGrpcAuther().Auth }
// WithPerRPCCredentials returns a DialOption which sets credentials and places // auth state on each outbound RPC. funcWithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption { return newFuncDialOption(func(o *dialOptions) { o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds) }) }
我们可以看到 PerRPCCredentials 是一个接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// PerRPCCredentials defines the common interface for the credentials which need to // attach security information to every RPC (e.g., oauth2). type PerRPCCredentials interface { // GetRequestMetadata gets the current request metadata, refreshing // tokens if required. This should be called by the transport layer on // each request, and the data should be populated in headers or other // context. If a status code is returned, it will be used as the status // for the RPC. uri is the URI of the entry point for the request. // When supported by the underlying implementation, ctx can be used for // timeout and cancellation. Additionally, RequestInfo data will be // available via ctx to this call. // TODO(zhaoq): Define the set of the qualified keys instead of leaving // it as an arbitrary string. GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) // RequireTransportSecurity indicates whether the credentials requires // transport security. RequireTransportSecurity() bool }
func(a *grpcAuther) streamAuth(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { // 从上下文中获取认证信息 md, ok := metadata.FromIncomingContext(ss.Context()) if !ok { return fmt.Errorf("ctx is not an grpc incoming context") } fmt.Println("gprc header info: ", md)