diff --git a/packages/node_modules/@node-red/runtime/lib/index.js b/packages/node_modules/@node-red/runtime/lib/index.js index b78d7d372..b869ef3ce 100644 --- a/packages/node_modules/@node-red/runtime/lib/index.js +++ b/packages/node_modules/@node-red/runtime/lib/index.js @@ -207,8 +207,12 @@ function start() { if (settings.readOnly){ log.info(log._("settings.readonly-mode")) } - if (settings.httpStatic) { - log.info(log._("runtime.paths.httpStatic",{path:path.resolve(settings.httpStatic)})); + if (settings.httpStatic && settings.httpStatic.length) { + for (let si = 0; si < settings.httpStatic.length; si++) { + let p = path.resolve(settings.httpStatic[si].path); + let r = settings.httpStatic[si].root || "/"; + log.info(log._("runtime.paths.httpStatic",{path:`${p} > ${r}`})); + } } return redNodes.loadContextsPlugin().then(function () { redNodes.loadFlows().then(redNodes.startFlows).catch(function(err) {}); diff --git a/packages/node_modules/node-red/red.js b/packages/node_modules/node-red/red.js index 2af02e2d5..4132e2db6 100755 --- a/packages/node_modules/node-red/red.js +++ b/packages/node_modules/node-red/red.js @@ -298,6 +298,26 @@ httpsPromise.then(function(startupHttps) { settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth; } + if(settings.httpStatic) { + settings.httpStaticRoot = formatRoot(settings.httpStaticRoot || "/"); + const statics = Array.isArray(settings.httpStatic) ? settings.httpStatic : [settings.httpStatic]; + const sanitised = []; + for (let si = 0; si < statics.length; si++) { + let sp = statics[si]; + if(typeof sp === "string") { + sp = { path: sp, root: "" } + sanitised.push(sp); + } else if (typeof sp === "object" && sp.path ) { + sanitised.push(sp); + } else { + continue; + } + sp.subRoot = formatRoot(sp.root); + sp.root = formatRoot(path.posix.join(settings.httpStaticRoot,sp.subRoot)); + } + settings.httpStatic = sanitised.length ? sanitised : false; + } + // if we got a port from command line, use it (even if 0) // replicate (settings.uiPort = parsedArgs.port||settings.uiPort||1880;) but allow zero if (parsedArgs.port !== undefined){ @@ -390,12 +410,28 @@ httpsPromise.then(function(startupHttps) { if (settings.httpNodeRoot !== false) { app.use(settings.httpNodeRoot,RED.httpNode); } + // if (settings.httpStatic) { + // settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth; + // if (settings.httpStaticAuth) { + // app.use("/",basicAuthMiddleware(settings.httpStaticAuth.user,settings.httpStaticAuth.pass)); + // } + // app.use("/",express.static(settings.httpStatic)); + // } if (settings.httpStatic) { - settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth; - if (settings.httpStaticAuth) { - app.use("/",basicAuthMiddleware(settings.httpStaticAuth.user,settings.httpStaticAuth.pass)); + let appUseMem = {}; + for (let si = 0; si < settings.httpStatic.length; si++) { + const sp = settings.httpStatic[si]; + const filePath = sp.path; + const thisRoot = sp.root || "/"; + if(appUseMem[filePath + "::" + thisRoot]) { + continue;// this path and root already registered! + } + appUseMem[filePath + "::" + thisRoot] = true; + if (settings.httpStaticAuth) { + app.use(thisRoot, basicAuthMiddleware(settings.httpStaticAuth.user, settings.httpStaticAuth.pass)); + } + app.use(thisRoot, express.static(filePath)); } - app.use("/",express.static(settings.httpStatic)); } function getListenPath() { diff --git a/packages/node_modules/node-red/settings.js b/packages/node_modules/node-red/settings.js index 33260e9b9..65d20e907 100644 --- a/packages/node_modules/node-red/settings.js +++ b/packages/node_modules/node-red/settings.js @@ -137,6 +137,7 @@ module.exports = { * - httpNodeCors * - httpNodeMiddleware * - httpStatic + * - httpStaticRoot ******************************************************************************/ /** the tcp port that the Node-RED web server is listening on */ @@ -218,8 +219,25 @@ module.exports = { /** When httpAdminRoot is used to move the UI to a different root path, the * following property can be used to identify a directory of static content * that should be served at http://localhost:1880/. + * When httpStaticRoot is set differently to httpAdminRoot, there is no need + * to move httpAdminRoot */ - //httpStatic: '/home/nol/node-red-static/', + //httpStatic: '/home/nol/node-red-static/', //single static source + /* OR multiple static sources can be created using an array of objects... */ + //httpStatic: [ + // {path: '/home/nol/pics/', root: "/img/"}, + // {path: '/home/nol/reports/', root: "/doc/"}, + //], + + /** + * All static routes will be appended to httpStaticRoot + * e.g. if httpStatic = "/home/nol/docs" and httpStaticRoot = "/static/" + * then "/home/nol/docs" will be served at "/static/" + * e.g. if httpStatic = [{path: '/home/nol/pics/', root: "/img/"}] + * and httpStaticRoot = "/static/" + * then "/home/nol/pics/" will be served at "/static/img/" + */ + //httpStaticRoot: '/static/', /******************************************************************************* * Runtime Settings