Hi All,
Hopefully the title says it all but when developing custom nodes whats the recommended approach to serving static content in say ./docs? I know httpStatic can be used in settings.js but thats locally set right? Is there a recommended way to dynamically update this?
Thanks
Hi @gazoscalvertos
For this, you will use the resources directory I believe.
It's like httpStatic, but on a per node basis.
I use this to host my own JS files and various resources that is accessed via the browser
https://nodered.org/docs/creating-nodes/resources
To access a file in your resources directory (example docs.html)
http://x.x.x.x:1880/resources/node-red-node-example/docs.html
Thanks, I'm using that for static content such as images etc, but thought there might have been a way to have a cleaner URL ie. https://noderedurl/documentation
I'll use the resources dir. 
You can attach your own routes to Node-RED's ExpressJS server if you want to. Just remember to remove them in the close callback otherwise you can end up with multiple instances.
Thanks, with a bit of testing I've managed to figure this out, might not be the most elegant of solutions but here is what works for me:
// grab the node express instance
const server = RED.httpNode;
try {
// set a route to /docs and handle subdirs
server.get('/docs/:resourcePath(*)', function (req, res) {
// handle default file ie index.html
const resourcePath = req.params.resourcePath || 'index.html';
const filePath = path.join(__dirname, '../docs', resourcePath);
// Determine the content type based on the file's extension
const contentType = mime.lookup(filePath);
// Read the data from the file
fs.readFile(filePath, (err, data) => {
if (err) {
// Handle errors, e.g., file not found
res.status(404).send('File not found');
} else {
// Set the content type and send the data in the response
res.set('Content-Type', contentType);
res.send(data);
}
});
});
} catch (error) {
console.log(error);
}
You need to be extremely! careful going with this approach.
Once a resource handler has been set - it can't be re-used.
Therefore, someone else developing this method (with the same endpoint) - won't see any issues, until one of their users also has your node installed.
or your users, complaining that they can't get to /docs/ - surprise surprise another node is using this endpoint.
I strongly encourage you to make it unique or use the resources method that is built-in to facilitate this need 
Thanks Marcus, that's a very good point! I'll probably stick to the resources method in that case.
I'll check I don't have anything else which could cause a clash (css etc)
I mean if you really needed to do it this way.
Maybe use a prefix to the URI or something to partition it away from other things.
Example: before I started using Resources with my ZWave Node I used to do:
server.get('/zwjs/api/:call', function (req, res) {})
server.get('/zwjs/docs/device/:part', function (req, res) {})
server.get('/zwjs/docs/controller/:part', function (req, res) {})
Absolutely you need to make sure that you use unique endpoints. Note how uibuilder goes to some length for example to make sure.
Also, you don't need to manually serve files. You can use Express Static. Serving static files in Express (expressjs.com)