diff --git a/red/api/index.js b/red/api/index.js index 48ae6fcff..a84751573 100644 --- a/red/api/index.js +++ b/red/api/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2014, 2015 IBM Corp. + * Copyright 2014, 2016 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ var log; var adminApp; var nodeApp; var server; +var runtime; var errorHandler = function(err,req,res,next) { if (err.message === "request entity too large") { @@ -51,8 +52,18 @@ var errorHandler = function(err,req,res,next) { res.status(400).json({error:"unexpected_error", message:err.toString()}); }; -function init(_server,runtime) { +var ensureRuntimeStarted = function(req,res,next) { + if (!runtime.isStarted()) { + log.error("Node-RED runtime not started"); + res.status(503).send("Not started"); + } else { + next(); + } +} + +function init(_server,_runtime) { server = _server; + runtime = _runtime; var settings = runtime.settings; i18n = runtime.i18n; log = runtime.log; @@ -75,7 +86,7 @@ function init(_server,runtime) { if (!settings.disableEditor) { ui.init(runtime); var editorApp = express(); - editorApp.get("/",ui.ensureSlash,ui.editor); + editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor); editorApp.get("/icons/:icon",ui.icon); theme.init(runtime); if (settings.editorTheme) { diff --git a/red/runtime/index.js b/red/runtime/index.js index 723141011..5bf9a2f0e 100644 --- a/red/runtime/index.js +++ b/red/runtime/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2013, 2015 IBM Corp. + * Copyright 2013, 2016 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,8 @@ var os = require("os"); var runtimeMetricInterval = null; +var started = false; + var stubbedExpressApp = { get: function() {}, post: function() {}, @@ -142,6 +144,7 @@ function start() { log.info(log._("runtime.paths.settings",{path:settings.settingsFile})); } redNodes.loadFlows().then(redNodes.startFlows); + started = true; }).otherwise(function(err) { console.log(err); }); @@ -173,6 +176,7 @@ function stop() { clearInterval(runtimeMetricInterval); runtimeMetricInterval = null; } + started = false; return redNodes.stopFlows(); } @@ -190,5 +194,8 @@ var runtime = module.exports = { events: events, nodes: redNodes, util: require("./util"), - get adminApi() { return adminApi } + get adminApi() { return adminApi }, + isStarted: function() { + return started; + } } diff --git a/test/red/api/index_spec.js b/test/red/api/index_spec.js index ef1ae4294..b73444eb1 100644 --- a/test/red/api/index_spec.js +++ b/test/red/api/index_spec.js @@ -1,5 +1,5 @@ /** - * Copyright 2014 IBM Corp. + * Copyright 2014, 2016 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,6 +87,45 @@ describe("api index", function() { }); }); + describe("editor warns if runtime not started", function() { + var mockList = [ + 'nodes','flows','library','info','theme','locales','credentials' + ] + before(function() { + mockList.forEach(function(m) { + sinon.stub(require("../../../red/api/"+m),"init",function(){}); + }); + }); + after(function() { + mockList.forEach(function(m) { + require("../../../red/api/"+m).init.restore(); + }) + }); + + it('serves the editor', function(done) { + var errorLog = sinon.spy(); + api.init({},{ + log:{audit:function(){},error:errorLog}, + settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false}, + events:{on:function(){},removeListener:function(){}}, + isStarted: function() { return false; } // <----- + }); + app = api.adminApp; + request(app) + .get("/") + .expect(503) + .end(function(err,res) { + if (err) { + return done(err); + } + res.text.should.eql("Not started"); + errorLog.calledOnce.should.be.true; + done(); + }); + }); + + }); + describe("enables editor", function() { var mockList = [ @@ -107,7 +146,8 @@ describe("api index", function() { api.init({},{ log:{audit:function(){}}, settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false}, - events:{on:function(){},removeListener:function(){}} + events:{on:function(){},removeListener:function(){}}, + isStarted: function() { return true; } }); app = api.adminApp; });