Loading default edit page values from packaged JSON?

Well, my node is all well and good when NodeRed is hosted at an unsecure http:// address. However, my fancy edit page code to load a list of values from a remote server doesn't work when NodeRed is secured at an https:// address because you can't make an ajax call to http from inside https.

Alas the real fix, calling https, is impossible since the service I'm calling doesn't support it.

Instead what I want to do in this situation is load a set of default values from a json file. I have the json file with the default values, but I can't for the life of me figure out how to load it at edit page display time. I tried doing $.getJSON("defaults.json") but that tries to load from the root of the server, not the folder my node is installed to.

Anyone have an example of loading a json from a nodered package when displaying the HTML edit page for the node?

Drawing on the example from earlier today, this is basically exactly what I'm after:

I guess what I'm missing is knowledge of what the path should be to access the file that I'm installing along with my node. Any pointers to what that path should be?

Have you thought about adding an httpAdmin endpoint to the node’s JS package, and inside that endpoint load the local file, read it out and send the results back in the response? Doing so means you place an http call to the local Node-RED instance rather than to a remote server, and as it has the same protocol/port/domain as the editor it shouldn’t lead to any issues. I’ll try to upload an example from one of my unpublished nodes that does this after I make dinner.

1 Like

I hadn't since I wasn't aware that's possible but it does sound like a reasonable solution.

To be honest I wound up just hardcoding the arrays with the default values right into the HTML. They're pretty much always going to be needed so fetching them remotely didn't really make any sense anymore.

I've a rather complex node, where for a config node that handles the connection to an OAuth 1.0a API requires extra setup behind the scenes. Most users won't need to touch any of that, but some might to change behaviour or options that the node offers (specifically, so that it can be released with only support for a public API, but also expose the internal API that uses the same endpoints and authorisation layer without releasing those endpoints and parameters publicly). To do so, I populate the configuration node at creation time (in the editor) with a default set of parameters that are loaded from a JSON file that resides in the node that holds the default bindings, and for advanced users those can be edited or more added to it. Rather than hardcoding those in the node, to allow editing of them I'm loading them from that JSON file.

I use a definitions-default.js file that could probably have been a JSON file too, but inside it holds the whole contents in a module.exports = { ... } structure. In the node's JavaScript file I've defined an httpAdmin endpoint that requires the file, then sends out a JSON response with the contents of it:

RED.httpAdmin.get('/aiotumblr-credentials/default-defs.json', function(req, res) {
    const definitions = require('./definitions-default.js');
    res.json(definitions);
});

Then, in the editor's oneditprepare I check if the node is new by seeing if there's already definitions added to it, and if not I'll populate them with the default set from that file:

if (this.definitions === {}) {
    // New config node, populate with the initial set of definitions.
    $.getJSON('aiotumblr-credentials/default-defs.json', function(data) {
        node.definitions = data.definitions;
        node.groups = data.groups;
    });
}

That way, upon first opening the configuration screen it's already filled with the default set from the file.

1 Like

Makes a ton of sense, thank you for sharing the samples. I'll keep this in mind for next time I need to do something like this, and hopefully others in the future will see it!

Edit: This approach is just what I needed to implement auto-discover, since it would suffer from the same issue (http calls from an https site). I just stubbed through what you described above as a test and it worked beautifully ("Hi!" was returned from the get() request).

Took me a bit of futzing since I'm writing this all in TypeScript but once I added the Express types I was good to go. Thankfully I used Express in another project so it's not totally new territory for me!

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