From e6cf783d5207b9873ce9dc488202355a9270bf22 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sat, 15 Feb 2014 22:36:01 +0000 Subject: [PATCH 1/6] HTTP In GET error handler fix --- nodes/core/io/21-httpin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/core/io/21-httpin.js b/nodes/core/io/21-httpin.js index 5af17fbb7..32073c5bb 100644 --- a/nodes/core/io/21-httpin.js +++ b/nodes/core/io/21-httpin.js @@ -58,7 +58,7 @@ function HTTPIn(n) { else node.send({req:req,res:res}); } if (this.method == "get") { - RED.app.get(this.url,this.callback,errorHandler); + RED.app.get(this.url,this.callback,this.errorHandler); } else if (this.method == "post") { RED.app.post(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); } else if (this.method == "put") { From 7c24d4d76045a694b6db650d3e0e6aecd56be988 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sun, 16 Feb 2014 00:39:30 +0000 Subject: [PATCH 2/6] Separate out httpAdmin and httpNode --- nodes/core/core/20-inject.js | 2 +- nodes/core/core/58-debug.js | 4 +-- nodes/core/io/10-mqtt.js | 6 ++-- nodes/core/io/21-httpin.html | 2 +- nodes/core/io/21-httpin.js | 10 +++--- nodes/core/io/22-websocket.html | 4 +-- nodes/core/io/22-websocket.js | 2 +- nodes/core/io/25-serial.js | 2 +- nodes/core/social/27-twitter.js | 8 ++--- public/red/main.js | 8 ++++- red.js | 56 ++++++++++++++++++++++++--------- red/red.js | 4 ++- red/server.js | 4 +++ red/ui.js | 30 +++++++++++------- settings.js | 34 ++++++++++++++++---- 15 files changed, 121 insertions(+), 55 deletions(-) diff --git a/nodes/core/core/20-inject.js b/nodes/core/core/20-inject.js index ee6100b71..952528f3e 100644 --- a/nodes/core/core/20-inject.js +++ b/nodes/core/core/20-inject.js @@ -83,7 +83,7 @@ InjectNode.prototype.close = function() { } } -RED.app.post("/inject/:id", function(req,res) { +RED.httpAdmin.post("/inject/:id", function(req,res) { var node = RED.nodes.getNode(req.params.id); if (node != null) { try { diff --git a/nodes/core/core/58-debug.js b/nodes/core/core/58-debug.js index 27d3bbd6f..1b67cc8b0 100644 --- a/nodes/core/core/58-debug.js +++ b/nodes/core/core/58-debug.js @@ -80,7 +80,7 @@ DebugNode.send = function(msg) { DebugNode.activeConnections = []; -var path = RED.settings.httpRoot || "/"; +var path = RED.settings.httpAdminRoot || "/"; path = path + (path.slice(-1) == "/" ? "":"/") + "debug/ws"; DebugNode.wsServer = new ws.Server({server:RED.server,path:path}); @@ -104,7 +104,7 @@ DebugNode.logHandler.on("log",function(msg) { }); RED.nodes.addLogHandler(DebugNode.logHandler); -RED.app.post("/debug/:id/:state", function(req,res) { +RED.httpAdmin.post("/debug/:id/:state", function(req,res) { var node = RED.nodes.getNode(req.params.id); var state = req.params.state; if (node != null) { diff --git a/nodes/core/io/10-mqtt.js b/nodes/core/io/10-mqtt.js index f729d286b..410ca2a0b 100644 --- a/nodes/core/io/10-mqtt.js +++ b/nodes/core/io/10-mqtt.js @@ -33,7 +33,7 @@ RED.nodes.registerType("mqtt-broker",MQTTBrokerNode); var querystring = require('querystring'); -RED.app.get('/mqtt-broker/:id',function(req,res) { +RED.httpAdmin.get('/mqtt-broker/:id',function(req,res) { var credentials = RED.nodes.getCredentials(req.params.id); if (credentials) { res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); @@ -42,12 +42,12 @@ RED.app.get('/mqtt-broker/:id',function(req,res) { } }); -RED.app.delete('/mqtt-broker/:id',function(req,res) { +RED.httpAdmin.delete('/mqtt-broker/:id',function(req,res) { RED.nodes.deleteCredentials(req.params.id); res.send(200); }); -RED.app.post('/mqtt-broker/:id',function(req,res) { +RED.httpAdmin.post('/mqtt-broker/:id',function(req,res) { var body = ""; req.on('data', function(chunk) { body+=chunk; diff --git a/nodes/core/io/21-httpin.html b/nodes/core/io/21-httpin.html index 2cc84a570..9be7d5a60 100644 --- a/nodes/core/io/21-httpin.html +++ b/nodes/core/io/21-httpin.html @@ -80,7 +80,7 @@ if (this.name) { return this.name; } else if (this.url) { - var root = document.location.pathname.slice(0,-1); + var root = RED.settings.httpNodeRoot.slice(0,-1); root += this.url; return "["+this.method+"] "+root; } else { diff --git a/nodes/core/io/21-httpin.js b/nodes/core/io/21-httpin.js index 32073c5bb..72d4d6e14 100644 --- a/nodes/core/io/21-httpin.js +++ b/nodes/core/io/21-httpin.js @@ -58,17 +58,17 @@ function HTTPIn(n) { else node.send({req:req,res:res}); } if (this.method == "get") { - RED.app.get(this.url,this.callback,this.errorHandler); + RED.httpNode.get(this.url,this.callback,this.errorHandler); } else if (this.method == "post") { - RED.app.post(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); + RED.httpNode.post(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); } else if (this.method == "put") { - RED.app.put(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); + RED.httpNode.put(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); } else if (this.method == "delete") { - RED.app.delete(this.url,this.callback,errorHandler); + RED.httpNode.delete(this.url,this.callback,errorHandler); } this.on("close",function() { - var routes = RED.app.routes[this.method]; + var routes = RED.httpNode.routes[this.method]; for (var i in routes) { if (routes[i].path == this.url) { routes.splice(i,1); diff --git a/nodes/core/io/22-websocket.html b/nodes/core/io/22-websocket.html index d6d15d20f..4052579cd 100644 --- a/nodes/core/io/22-websocket.html +++ b/nodes/core/io/22-websocket.html @@ -135,12 +135,12 @@ inputs:0, outputs:0, label: function() { - var root = document.location.pathname.slice(0,-1); + var root = RED.settings.httpNodeRoot.slice(0,-1); root += this.path; return root; }, oneditprepare: function() { - var root = document.location.pathname.slice(0,-1); + var root = RED.settings.httpNodeRoot.slice(0,-1); if (root == "") { $("#node-config-ws-tip").hide(); } else { diff --git a/nodes/core/io/22-websocket.js b/nodes/core/io/22-websocket.js index da2a3fe57..4638dd1ba 100644 --- a/nodes/core/io/22-websocket.js +++ b/nodes/core/io/22-websocket.js @@ -32,7 +32,7 @@ function WebSocketListenerNode(n) { node._inputNodes = []; // collection of nodes that want to receive events - var path = RED.settings.httpRoot || "/"; + var path = RED.settings.httpNodeRoot || "/"; path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path); // Workaround https://github.com/einaros/ws/pull/253 diff --git a/nodes/core/io/25-serial.js b/nodes/core/io/25-serial.js index de016fb05..3e1fa4878 100644 --- a/nodes/core/io/25-serial.js +++ b/nodes/core/io/25-serial.js @@ -185,7 +185,7 @@ var serialPool = function() { } }(); -RED.app.get("/serialports",function(req,res) { +RED.httpAdmin.get("/serialports",function(req,res) { serialp.list(function (err, ports) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.write(JSON.stringify(ports)); diff --git a/nodes/core/social/27-twitter.js b/nodes/core/social/27-twitter.js index 68852bada..fc377205c 100644 --- a/nodes/core/social/27-twitter.js +++ b/nodes/core/social/27-twitter.js @@ -263,7 +263,7 @@ var oa = new OAuth( var credentials = {}; -RED.app.get('/twitter/:id', function(req,res) { +RED.httpAdmin.get('/twitter/:id', function(req,res) { var credentials = RED.nodes.getCredentials(req.params.id); if (credentials) { res.send(JSON.stringify({sn:credentials.screen_name})); @@ -272,12 +272,12 @@ RED.app.get('/twitter/:id', function(req,res) { } }); -RED.app.delete('/twitter/:id', function(req,res) { +RED.httpAdmin.delete('/twitter/:id', function(req,res) { RED.nodes.deleteCredentials(req.params.id); res.send(200); }); -RED.app.get('/twitter/:id/auth', function(req, res){ +RED.httpAdmin.get('/twitter/:id/auth', function(req, res){ var credentials = {}; oa.getOAuthRequestToken({ oauth_callback: req.query.callback @@ -297,7 +297,7 @@ RED.app.get('/twitter/:id/auth', function(req, res){ }); }); -RED.app.get('/twitter/:id/auth/callback', function(req, res, next){ +RED.httpAdmin.get('/twitter/:id/auth/callback', function(req, res, next){ var credentials = RED.nodes.getCredentials(req.params.id); credentials.oauth_verifier = req.query.oauth_verifier; diff --git a/public/red/main.js b/public/red/main.js index 0ba4cbd47..816bd7168 100644 --- a/public/red/main.js +++ b/public/red/main.js @@ -122,6 +122,12 @@ var RED = function() { ] }); + function loadSettings() { + $.get('settings', function(data) { + RED.settings = data; + loadNodes(); + }); + } function loadNodes() { $.get('nodes', function(data) { $("body").append(data); @@ -157,7 +163,7 @@ var RED = function() { $(function() { RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); - loadNodes(); + loadSettings(); }); return { diff --git a/red.js b/red.js index 38bcc345d..dcb030046 100644 --- a/red.js +++ b/red.js @@ -48,31 +48,57 @@ if (settings.https) { server = http.createServer(function(req,res){app(req,res);}); } +function formatRoot(root) { + if (root[0] != "/") { + root = "/" + root; + } + if (root.slice(-1) != "/") { + root = root + "/"; + } + return root; +} + settings.httpRoot = settings.httpRoot||"/"; -if (settings.httpRoot[0] != "/") { - settings.httpRoot = "/"+settings.httpRoot; -} -if (settings.httpRoot.slice(-1) != "/") { - settings.httpRoot = settings.httpRoot + "/"; -} +settings.httpAdminRoot = formatRoot(settings.httpAdminRoot || settings.httpRoot || "/"); +settings.httpAdminAuth = settings.httpAdminAuth || settings.httpAuth; + +settings.httpNodeRoot = formatRoot(settings.httpNodeRoot || settings.httpRoot || "/"); +settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth; + settings.uiPort = settings.uiPort||1880; settings.uiHost = settings.uiHost||"0.0.0.0"; -if (settings.httpAuth) { - app.use(settings.httpRoot, +settings.flowFile = flowFile || settings.flowFile; + +RED.init(server,settings); + +if (settings.httpAdminAuth) { + app.use(settings.httpAdminRoot, express.basicAuth(function(user, pass) { - return user === settings.httpAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAuth.pass; + return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; }) ); } - -settings.flowFile = flowFile || settings.flowFile; - -var red = RED.init(server,settings); -app.use(settings.httpRoot,red); +if (settings.httpNodeAuth) { + app.use(settings.httpNodeRoot, + express.basicAuth(function(user, pass) { + return user === settings.httpNodeAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpNodeAuth.pass; + }) + ); +} +app.use(settings.httpAdminRoot,RED.httpAdmin); +app.use(settings.httpNodeRoot,RED.httpNode); if (settings.httpStatic) { + settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth; + if (settings.httpStaticAuth) { + app.use("/", + express.basicAuth(function(user, pass) { + return user === settings.httpStaticAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpStaticAuth.pass; + }) + ); + } app.use("/",express.static(settings.httpStatic)); } @@ -80,7 +106,7 @@ RED.start(); var listenPath = 'http'+(settings.https?'s':'')+'://'+ (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+ - ':'+settings.uiPort+settings.httpRoot; + ':'+settings.uiPort+settings.httpAdminRoot; server.listen(settings.uiPort,settings.uiHost,function() { util.log('[red] Server now running at '+listenPath); diff --git a/red/red.js b/red/red.js index 49d19aa07..5e5641930 100644 --- a/red/red.js +++ b/red/red.js @@ -42,7 +42,9 @@ var RED = { events: events }; -RED.__defineGetter__("app", function() { return server.app }); +RED.__defineGetter__("app", function() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return server.app }); +RED.__defineGetter__("httpAdmin", function() { return server.app }); +RED.__defineGetter__("httpNode", function() { return server.nodeApp }); RED.__defineGetter__("server", function() { return server.server }); RED.__defineGetter__("settings", function() { return settings }); diff --git a/red/server.js b/red/server.js index e292a36ee..ec1509a71 100644 --- a/red/server.js +++ b/red/server.js @@ -14,11 +14,13 @@ * limitations under the License. **/ +var express = require('express'); var util = require('util'); var createUI = require("./ui"); var redNodes = require("./nodes"); var app = null; +var nodeApp = null; var server = null; var settings = null; var storage = null; @@ -28,6 +30,7 @@ function createServer(_server,_settings) { settings = _settings; storage = require("./storage"); app = createUI(settings); + nodeApp = express(); flowfile = settings.flowFile || 'flows_'+require('os').hostname()+'.json'; @@ -103,4 +106,5 @@ module.exports = { } module.exports.__defineGetter__("app", function() { return app }); +module.exports.__defineGetter__("nodeApp", function() { return nodeApp }); module.exports.__defineGetter__("server", function() { return server }); diff --git a/red/ui.js b/red/ui.js index 0592fc058..33449d34a 100644 --- a/red/ui.js +++ b/red/ui.js @@ -34,24 +34,30 @@ function setupUI(settings) { // Need to ensure the url ends with a '/' so the static serving works // with relative paths app.get("/",function(req,res) { - if (req.originalUrl.slice(-1) != "/") { - res.redirect(req.originalUrl+"/"); - } else { - req.next(); - } + if (req.originalUrl.slice(-1) != "/") { + res.redirect(req.originalUrl+"/"); + } else { + req.next(); + } }); app.get("/icons/:icon",function(req,res) { - for (var p in icon_paths) { - if (fs.existsSync(icon_paths[p]+'/'+req.params.icon)) { - res.sendfile(icon_paths[p]+'/'+req.params.icon); - return; - } + for (var p in icon_paths) { + if (fs.existsSync(icon_paths[p]+'/'+req.params.icon)) { + res.sendfile(icon_paths[p]+'/'+req.params.icon); + return; } - //TODO: create a default icon - res.sendfile(path.resolve(__dirname + '/../public/icons/arrow-in.png')); + } + //TODO: create a default icon + res.sendfile(path.resolve(__dirname + '/../public/icons/arrow-in.png')); }); + app.get("/settings", function(req,res) { + var safeSettings = { + httpNodeRoot: settings.httpNodeRoot + }; + res.json(safeSettings); + }); app.use("/",express.static(__dirname + '/../public')); diff --git a/settings.js b/settings.js index 10a9c01aa..e941a19db 100644 --- a/settings.js +++ b/settings.js @@ -49,19 +49,41 @@ module.exports = { // The following property can be used to specify an additional directory to scan. //nodesDir: '/home/nol/.node-red/nodes', - // You can protect the user interface with a userid and password by using the following property - // the password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') - //httpAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, - // By default, the Node-RED UI is available at http://localhost:1880/ // The following property can be used to specifiy a different root path. - //httpRoot: '/admin', + //httpAdminRoot: '/admin', - // When httpRoot is used to move the UI to a different root path, the + // You can protect the user interface with a userid and password by using the following property. + // The password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') + //httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, + + // Some nodes, such as HTTP In, can be used to listen for incoming http requests. + // By default, these are served relative to '/'. The following property + // can be used to specifiy a different root path. + //httpNodeRoot: '/nodes', + + // To password protect the node-defined HTTP endpoints, the following property + // can be used. + // The password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') + //httpNodeAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, + + // 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/. //httpStatic: '/home/nol/node-red-dashboard/', + // To password protect the static content, the following property can be used. + // The password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') + //httpStaticAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, + + // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot', + // to apply the same root to both parts. + //httpRoot: '/red', + + // The following property can be used in place of 'httpAdminAuth' and 'httpNodeAuth', + // to apply the same authentication to both parts. + //httpAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, + // The following property can be used to enable HTTPS // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener // for details on its contents. From b7e3e2d739399beb9b78de20bc67b98b7be72a75 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sun, 16 Feb 2014 23:17:15 +0000 Subject: [PATCH 3/6] Add username/password to Mongo nodes Fixes #159 --- nodes/core/storage/66-mongodb.html | 53 ++++++++++- nodes/core/storage/66-mongodb.js | 147 ++++++++++++++++++++--------- 2 files changed, 149 insertions(+), 51 deletions(-) diff --git a/nodes/core/storage/66-mongodb.html b/nodes/core/storage/66-mongodb.html index a7c4857a4..3a2490440 100644 --- a/nodes/core/storage/66-mongodb.html +++ b/nodes/core/storage/66-mongodb.html @@ -29,6 +29,14 @@ +
+ + +
+
+ + +
@@ -110,7 +155,7 @@ align: "right", label: function() { var mongoNode = RED.nodes.node(this.mongodb); - return this.name||(mongoNode?mongoNode.label()+"//"+this.collection:"mongodb"); + return this.name||(mongoNode?mongoNode.label()+" "+this.collection:"mongodb"); }, labelStyle: function() { return this.name?"node_label_italic":""; @@ -154,7 +199,7 @@ icon: "mongodb.png", label: function() { var mongoNode = RED.nodes.node(this.mongodb); - return this.name||(mongoNode?mongoNode.label()+"//"+this.collection:"mongodb"); + return this.name||(mongoNode?mongoNode.label()+" "+this.collection:"mongodb"); }, labelStyle: function() { return this.name?"node_label_italic":""; diff --git a/nodes/core/storage/66-mongodb.js b/nodes/core/storage/66-mongodb.js index 4340a2634..897c03b6d 100644 --- a/nodes/core/storage/66-mongodb.js +++ b/nodes/core/storage/66-mongodb.js @@ -16,6 +16,7 @@ var RED = require(process.env.NODE_RED_HOME+"/red/red"); var mongo = require('mongodb'); +var MongoClient = mongo.MongoClient; function MongoNode(n) { RED.nodes.createNode(this,n); @@ -23,9 +24,62 @@ function MongoNode(n) { this.port = n.port; this.db = n.db; this.name = n.name; + var credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.username = credentials.user; + this.password = credentials.password; + } + + var url = "mongodb://"; + if (this.username && this.password) { + url += this.username+":"+this.password+"@"; + } + url += this.hostname+":"+this.port+"/"+this.db; + + this.url = url; } + RED.nodes.registerType("mongodb",MongoNode); +var querystring = require('querystring'); + +RED.httpAdmin.get('/mongodb/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); + } else { + res.send(JSON.stringify({})); + } +}); + +RED.httpAdmin.delete('/mongodb/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); +}); + +RED.httpAdmin.post('/mongodb/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.user == null || newCreds.user == "") { + delete credentials.user; + } else { + credentials.user = newCreds.user; + } + if (newCreds.password == "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); +}); + function MongoOutNode(n) { RED.nodes.createNode(this,n); @@ -37,34 +91,33 @@ function MongoOutNode(n) { if (this.mongoConfig) { var node = this; - this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); - this.clientDb.open(function(err,cli) { - if (err) { node.error(err); } - else { - node.clientDb.collection(node.collection,function(err,coll) { - if (err) { node.error(err); } - else { - node.on("input",function(msg) { - if (node.operation == "store") { - delete msg._topic; - if (node.payonly) { - if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } - coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); - } - else coll.save(msg,function(err,item){if (err){node.error(err);}}); - } - else if (node.operation == "insert") { - delete msg._topic; - if (node.payonly) { - if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } - coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); - } - else coll.insert(msg,function(err,item){if (err){node.error(err);}}); - } - if (node.operation == "delete") { - coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); - } - }); + MongoClient.connect(this.mongoConfig.url, function(err,db) { + if (err) { + node.error(err); + } else { + node.clientDb = db; + var coll = db.collection(node.collection); + node.on("input",function(msg) { + if (node.operation == "store") { + delete msg._topic; + if (node.payonly) { + if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } + coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); + } else { + coll.save(msg,function(err,item){if (err){node.error(err);}}); + } + } + else if (node.operation == "insert") { + delete msg._topic; + if (node.payonly) { + if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } + coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); + } else { + coll.insert(msg,function(err,item){if (err){node.error(err);}}); + } + } + if (node.operation == "delete") { + coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); } }); } @@ -90,25 +143,25 @@ function MongoInNode(n) { if (this.mongoConfig) { var node = this; - this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); - this.clientDb.open(function(err,cli) { - if (err) { node.error(err); } - else { - node.clientDb.collection(node.collection,function(err,coll) { - if (err) { node.error(err); } - else { - node.on("input",function(msg) { - msg.projection = msg.projection || {}; - coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { - if (err) { node.error(err); } - msg.payload = items; - delete msg.projection; - delete msg.sort; - delete msg.limit; - node.send(msg); - }); - }); - } + MongoClient.connect(this.mongoConfig.url, function(err,db) { + if (err) { + node.error(err); + } else { + node.clientDb = db; + var coll = db.collection(node.collection); + node.on("input",function(msg) { + msg.projection = msg.projection || {}; + coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { + if (err) { + node.error(err); + } else { + msg.payload = items; + delete msg.projection; + delete msg.sort; + delete msg.limit; + node.send(msg); + } + }); }); } }); From 09f162d9337904e0ca1d79aece210d5a0ace57e3 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 17 Feb 2014 22:16:42 +0000 Subject: [PATCH 4/6] Fix overriding method in HTTP Req node --- nodes/core/io/21-httpin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nodes/core/io/21-httpin.js b/nodes/core/io/21-httpin.js index 72d4d6e14..188510586 100644 --- a/nodes/core/io/21-httpin.js +++ b/nodes/core/io/21-httpin.js @@ -106,14 +106,14 @@ RED.nodes.registerType("http response",HTTPOut); function HTTPRequest(n) { RED.nodes.createNode(this,n); var nodeUrl = n.url; - var method = n.method || "GET"; + var nodeMethod = n.method || "GET"; var node = this; this.on("input",function(msg) { var url = msg.url||nodeUrl; - + var method = (msg.method||nodeMethod).toUpperCase(); var opts = urllib.parse(url); - opts.method = (msg.method||method).toUpperCase(); + opts.method = method; if (msg.headers) { opts.headers = msg.headers; } From 6b278fdceb6bf4f945a0b8a5a69c9e74021d2da8 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 17 Feb 2014 22:32:53 +0000 Subject: [PATCH 5/6] Add httpNodeCors setting Adds a dependency on the 'cors' npm module --- nodes/core/io/21-httpin.js | 40 +++++++++++++++++++++++++++++--------- package.json | 1 + settings.js | 9 +++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/nodes/core/io/21-httpin.js b/nodes/core/io/21-httpin.js index 188510586..557d30b96 100644 --- a/nodes/core/io/21-httpin.js +++ b/nodes/core/io/21-httpin.js @@ -21,6 +21,7 @@ var https = require("follow-redirects").https; var urllib = require("url"); var express = require("express"); var getBody = require('raw-body'); +var cors = require('cors'); var jsonParser = express.json(); var urlencParser = express.urlencoded(); @@ -53,28 +54,49 @@ function HTTPIn(n) { }; this.callback = function(req,res) { - if (node.method == "post") { node.send({req:req,res:res,payload:req.body}); } - else if (node.method == "get") { node.send({req:req,res:res,payload:req.query}); } - else node.send({req:req,res:res}); + if (node.method == "post") { + node.send({req:req,res:res,payload:req.body}); + } else if (node.method == "get") { + node.send({req:req,res:res,payload:req.query}); + } else { + node.send({req:req,res:res}); + } } + + var corsHandler = function(req,res,next) { next(); } + + if (RED.settings.httpNodeCors) { + corsHandler = cors(RED.settings.httpNodeCors); + RED.httpNode.options(this.url,corsHandler); + } + if (this.method == "get") { - RED.httpNode.get(this.url,this.callback,this.errorHandler); + RED.httpNode.get(this.url,corsHandler,this.callback,this.errorHandler); } else if (this.method == "post") { - RED.httpNode.post(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); + RED.httpNode.post(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); } else if (this.method == "put") { - RED.httpNode.put(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); + RED.httpNode.put(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); } else if (this.method == "delete") { - RED.httpNode.delete(this.url,this.callback,errorHandler); + RED.httpNode.delete(this.url,corsHandler,this.callback,errorHandler); } this.on("close",function() { - var routes = RED.httpNode.routes[this.method]; - for (var i in routes) { + var routes = RED.httpNode.routes[this.method]; + for (var i = 0; i Date: Mon, 17 Feb 2014 22:42:31 +0000 Subject: [PATCH 6/6] Add clientid to mqtt-broker label Fixes #161 --- nodes/core/io/10-mqtt.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/core/io/10-mqtt.html b/nodes/core/io/10-mqtt.html index 39f8f9373..e4d6c985d 100644 --- a/nodes/core/io/10-mqtt.html +++ b/nodes/core/io/10-mqtt.html @@ -132,7 +132,7 @@ }, label: function() { - return this.broker+":"+this.port; + return (this.clientid?this.clientid+"@":"")+this.broker+":"+this.port; }, oneditprepare: function() { $.getJSON('mqtt-broker/'+this.id,function(data) {