How to use variables entered in editor inside httpadmin function

I am trying to display a list of files from FTP server after successful authentication using basic-ftp package.

image

I want to use the variables entered in the editor inside the httpadmin function which makes a ftp call instead of the hard coded values shown below.

image

Is there a way I can pass the variables entered in editor inside the httpadmin call function

There are various ftp nodes already available.

If you want to use an npm module, you could also do this directly in a function node.

Enable this feature in settings.js:

   /** Allow the Function node to load additional npm modules directly */
    functionExternalModules: true,

Restart node-red.

Then type the module package name in the Setup tab and node-red will install it in the background:

and then in the "On Message" tab:

const client = new ftp.Client()
client.ftp.verbose = true
try {
    await client.access({
        host: msg.payload.ip,
        user: msg.payload.username,
        password: msg.payload.password,
        secure: false
    })
    
    node.send({payload:await client.list()}) // outputs the files in the directory

}
catch (err) {
    node.warn(err)
}
client.close()

Then you can pass properties directly without the need to create a full node.

Let me explain the complete flow:
I am trying to run ansible command with this node which I am creating.

So after entering correct details in editor the user will be connected to ftp server which then displays a list of files present in the server on the editor itself. So once the user selects the file and deploys it starts executing the ansible command.

So I wanted to know the following:

  1. Can we combine an already available ftp node on the editor of my custom node.
  2. Is it possible to pass the values entered in text fields to the httpadmin function where I can use the basic-ftp module and display the list of files.

I hope that you are going to make FTPS and SFTP and maybe SCP as secure options? In my professional realm, we don't allow raw FTP even internally since passing in the user and password happens unencrypted

No, each one has its own nodes. So you can include them in your flows but not in your own nodes.

I'm a bit confused about the "httpadmin" part? What do you mean by that? I assume that you mean the Node-RED Editor?

Certainly you can use fields entered in your custom node's Editor panel, that is the point. Have a look in the Node-RED docs concerning creating custom nodes. It explains how you do it.

I was referring to this httpAdmin function. So instead of the hard coded values in host, user etc. I want to pass the values obtained from my custom node's editor panel which I am not sure how it is done.

RED.httpAdmin.get(
    "/ftplist",
    RED.auth.needsPermission("ftplist.read"),

    async function (req, res) {
      t;

      ftpList = [];
      ftpListNames = [];
      hostAddress = "1";

      const client = new ftp.Client();
      client.ftp.verbose = true;
      try {
        await client.access({
          host: "192.168.109.140", //hard coded
          user: "testuser",
          password: "1234",
        });

        ftpList = await client.list("/files");

        for (let i = 0; i < ftpList.length; i++) {
          ftpListNames.push(ftpList[i].name);
        }
      } catch (err) {
        console.log(err);
      }
      client.close();
      res.json(ftpListNames);
    }
  );

That is a reference to the ExpressJS web server that serves up the Editor and other Node-RED admin features. That function is adding "middleware" to Express to define a new endpoint /ftplist. I expect you know that but just setting the scene for anyone else who might not.

It is basically setting up a new API that requires Editor permissions to access.

The settings from the Editor for your node are passed to your node's runtime js in the part of your js that is run when it calls RED.nodes.registerType That call takes a callback function that has a parameter typically referred to as config. In that callback, you typically transfer the settings from the front-end config object to the node (which represents the instance of your custom node definition). That is done by calling RED.nodes.createNode(this, config) and following that, this represents the instance of your node and you transfer the config settings to it with a series of statements like this.name = config.name ?? .

In my own custom nodes, I use a particular layout which I think is easier to parse. Check it out in node-red-contrib-uibuilder/customNode.js at v6.1.0 · TotallyInformation/node-red-contrib-uibuilder (github.com) as an example.

So getting back to the question, to be able to pick up the settings, you define the get callback in a position that has access to the node instance definition. I don't have a simple example I'm afraid because uibuilder - which makes use of several admin API's as well as several user-facing API's - is quite complex and has split the "web" type functions into a separate class. However, you will find an example here:

which is, as I describe above, in the callback function used when the node instance is actually instanciated. As you can see, what is sent back to the requestor (which will be in your node's html file) is actually provided by a call to a web class method. That gets the node instance object (this) passed to it in an argument along with the ExpressJS req (request) object.

PS: In most example code, you will see people immediately create a variable called node and pass this to it. I don't do that in my layout because it isn't needed. However, if I do pass the node instance to another function/method, I always call it node in the arguments.

@syedhannan if you want to use the values entered in the edit dialog, you can pass them over in the request you send to the backend.

The Inject node includes an example of how to do this with the 'inject now' button that was added in a recent release.

Rather than use a GET request, it uses a POST request, and passes the properties as the body of the request.

You can see the runtime side here: node-red/20-inject.js at master · node-red/node-red · GitHub

And the editor side here: node-red/20-inject.html at master · node-red/node-red · GitHub

The key parts are using the data property in the $.ajax(...) call to set the body of the request and setting contentType: "application/json; charset=utf-8" so the runtime knows how to parse it. Then in the runtime, accessing the values as req.body.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.