// HandleStreamingRPC is an internal method. Do not use! func (server *Server) HandleStreamingRPC( grpcStream core.LeverRPC_HandleStreamingRPCServer) error { ctx := grpcStream.Context() err := setInternalRPCGateway(ctx) if err != nil { return err } leverURL, err := extractLeverURL(ctx) if err != nil { return err } fstMsg, err := grpcStream.Recv() if err != nil { return err } rpc := fstMsg.GetRpc() if rpc == nil { return fmt.Errorf("First message needs to have RPC field set") } if rpc.GetArgsOneof() == nil { return fmt.Errorf("RPC has no args oneof") } // Reply with an empty msg (first response message must be empty). grpcStream.Send(&core.StreamMessage{}) server.lock.RLock() entry, handlerOK := server.streamingHandlers[leverURL.Method] resourceOK := true if leverURL.Resource != "" { _, resourceOK = server.resources[leverURL.Resource] } server.lock.RUnlock() if !handlerOK { return fmt.Errorf("Method not found") } if !resourceOK { return fmt.Errorf("Resource not found") } _, err = callHandler(ctx, leverURL.Resource, entry, rpc, grpcStream) return err }
func callHandler( ctx context.Context, resource string, entry *handlerEntry, rpc *core.RPC, grpcStream core.LeverRPC_HandleStreamingRPCServer) ( reply *core.RPCReply, err error) { // Prepare args for handler. var callArgs []reflect.Value if entry.isMethod { callArgs = append(callArgs, reflect.ValueOf(entry.obj)) } isStreaming := (grpcStream != nil) if isStreaming { callArgs = append( callArgs, reflect.ValueOf(newServerStream(grpcStream))) } else { if entry.hasContext { callArgs = append(callArgs, reflect.ValueOf(ctx)) } } if resource != "" { callArgs = append(callArgs, reflect.ValueOf(resource)) } switch args := rpc.GetArgsOneof().(type) { case *core.RPC_Args: var values []reflect.Value values, err = decodeArgsAsValue(args.Args, entry, isStreaming) if err != nil { return nil, err } callArgs = append(callArgs, values...) case *core.RPC_ByteArgs: callArgs = append(callArgs, reflect.ValueOf(args.ByteArgs)) default: return nil, fmt.Errorf("Invalid args") } // Call handler. result := reflect.ValueOf(entry.handler).Call(callArgs) // Interpret result. errIndex := 1 if isStreaming { errIndex = 0 } if entry.isByteErrorResult { var errBytesResult []byte v := result[errIndex].Interface() if v != nil { var ok bool errBytesResult, ok = result[errIndex].Interface().([]byte) if !ok { errBytesResult = result[errIndex].Interface().(BytesError).GetBytes() } if errBytesResult != nil { if !isStreaming { return &core.RPCReply{ ResultOneof: &core.RPCReply_ByteError{ ByteError: errBytesResult, }, }, nil } err = grpcStream.Send(&core.StreamMessage{ MessageOneof: &core.StreamMessage_ByteError{ ByteError: errBytesResult, }, }) return nil, err } } } else { v := result[errIndex].Interface() if v != nil { theError, isErrorType := v.(error) if isErrorType { // For error type, just use the string returned by Error(). v = theError.Error() } var encodedErr *core.JSON encodedErr, err = encodeArg(v) if err != nil { return nil, err } if !isStreaming { return &core.RPCReply{ ResultOneof: &core.RPCReply_Error{ Error: encodedErr, }, }, nil } err = grpcStream.Send(&core.StreamMessage{ MessageOneof: &core.StreamMessage_Error{ Error: encodedErr, }, }) return nil, err } } if isStreaming { // Stream case - no reply sent back. return nil, nil } // Non-stream case - build reply. if entry.isByteResult { return &core.RPCReply{ ResultOneof: &core.RPCReply_ByteResult{ ByteResult: result[0].Interface().([]byte), }, }, nil } encodedResult, err := encodeArg(result[0].Interface()) if err != nil { return nil, err } return &core.RPCReply{ ResultOneof: &core.RPCReply_Result{ Result: encodedResult, }, }, nil }