NodeJS Express - separate routes on two ports - node.js

I have an express server, and while building it created several "helper" functions on their own routes. I'd like those routes to be accessed on a different port. Is there anyway to do this in express?
In the code below, the "/factory" route (and other functionality) would be on one port, and the helper routes of "/killallthings", "/listallthings", and "/killserver" would be on a separate port.
Here is a simplified version of the code:
var express = require('express');
var things = [];
var app = express();
var port = 8080;
app.post('/factory/', function(req, res) {
//Create a thing and add it to the thing array
});
//Assume more functions to do to things here....
app.post('/killallthings/', function(req, res) {
//Destroy all the things in the array
});
app.post('/listallthings/', function(req, res) {
// Return a list of all the things
});
app.post('/killserver/', function(req,res){
//Kills the server after killing the things and doing clean up
});
//Assume https options properly setup.
var server = require('https').createServer(options, app);
server.listen(port, function() {
logger.writeLog('Listening on port ' + port);
});
Is this possible with express?

Based on Explosion Pills suggestion above, I modified the code in roughly this way:
var express = require('express');
var things = [];
var app = express();
var admin_app = express();
var port = 8080;
var admin_port = 8081;
app.post('/factory/', function(req, res) {
//Create a thing and add it to the thing array
});
//Assume more functions to do to things here....
admin_app.post('/killallthings/', function(req, res) {
//Destroy all the things in the array
});
admin_app.post('/listallthings/', function(req, res) {
// Return a list of all the things
});
admin_app.post('/killserver/', function(req,res){
//Kills the server after killing the things and doing clean up
});
//Assume https options properly setup.
var server = require('https').createServer(options, app);
server.listen(port, function() {
logger.writeLog('Listening on port ' + port);
});
var admin_server = require('https').createServer(options, admin_app);
admin_server.listen(admin_port, function() {
logger.writeLog('Listening on admin port ' + admin_port);
});
I wish I knew how to give Explosion Pills the credit for the answer! :)

If you are trying to create multiple servers then why not crate multiple bin/www files with different ports and configurations. Another way could be pass port number directly from command line.

Related

Socket.js inside controllers in server(Node.js)

I am on the process of building a chat application with nodejs, reactjs mongo and socket.io.My chat app consists of both one to one and group chats.I have built a schema for group chat and i am inserting group names along with its members and their chats in the table.Since im a beginner towards socket.io, I dont know where to put the socket logic that needs to be fired after the db post operation.Can some one suggest any examples for me?
Update your code accordingly:
=> server.js file
// Declare socket.io
const io = require('socket.io')(server);
// Add middleware to set socket.io in
app.use((req, res, next)=>{ res.locals['socketio'] = io; next(); });
=> In your controller file
// Get the value of socket.io
module.exports = your_function_name = (req, res) => {
const io = res.locals['socketio']
// Use io when you need.
});
Hope this solves your query.
You can separate you socket related code by following way :
==>app.js
var express = require('express');
var socket = require('./socketServer');
var app = express();
var server = app.listen((config.node_port || 3000), function () {
console.log('Listening on port ' + (config.node_port || 3000) + '...');
});
socket.socketStartUp(server);
module.exports = app;
==>socketServer.js
var io = require('socket.io')();
var socketFunction = {}
socketFunction.socketStartUp = function (server) {
io.attach(server);
io.on('connection', function (socket) {
console.log("New user is connected with socket:", socket.id);
})
}
module.exports = socketFunction;
You can also check node API startup code with socket functionality in below link:
Node API Start up
Hope this answer is helpful to you

Nodejs - BrowserSync running on express server

I want to pull a URL from the DB and use it as the proxied URL. However the setup I've come up with initializes a new BrowserSync server for each URL, using incrementing port numbers.
Is there a way to accomplish this without initializing a new BrowserSync server every time?
Or should I be using another approach?
var bs = require("browser-sync");
var express = require("express");
var router = express.Router();
var app = express();
router.get("/", function(req, res){
var proxyUrl = getUrl() //get url from db (www.example.com)
bs.create("bs1").init({
notify: false,
open: false,
ui: false,
port: 10000,
proxy: proxyUrl
});
res.send();
});
app.use(router);
app.listen(8080, function(){
console.log('listening on *:8080');
});
The above is fine(ish) but is it good practice to be initializing a new server for every URL (potentially thousands)?
And is it safe to be exposing a new port number to every user of the system? (Can I mask this with a subdomain?)
Update
My end goal is to use a unique subdomain to refer to each proxy url.
For example:
sub1.mysite.com proxies www.example.com,
sub2.mysite.com proxies www.example2.com
Browser-sync will not work as the proxy is tie to server setup.
I use following packages:
express
express-http-proxy
vhost (express vhost)
const port = 8080;
var app = require('express')();
var proxy = require('express-http-proxy');
var url = require('url');
var vhost = require('vhost');
app.listen(port);
/* Assuming getUrl() will return an array of sites */
// var sites = getUrl();
// DO NOT put '/' at the end of site
var sites = [
'http://www.bing.com',
'http://samanthagooden.com',
'http://www.courtleigh.com'
];
var i = 0;
sites.forEach(site => {
i++;
var subDomain = 'sub' + i + '.mysite.com';
app.use(vhost(subDomain, proxy(site, {
forwardPath: (req, res) => url.parse(req.url).path,
intercept: (rsp, data, req, res, callback) => {
if (res._headers['content-type']) {
var contentType = res._headers['content-type'];
if (
contentType.indexOf('text') !== -1 ||
contentType.indexOf('javascript') !== -1
) {
// Replace link if content-type = text or javascript
var reg = new RegExp(site, 'g');
res.send(data.toString().replace(reg, ''));
} else {
res.send(data);
}
} else {
res.send(data);
}
}
})));
console.log(subDomain + ':' + port + ' proxy: ' + site);
});
The above example will create following proxies:
sub1.mysite.com:8080 proxy: www.bing.com
sub2.mysite.com:8080 proxy: www.example.com
Maybe I'm misunderstanding what you are trying to do, but Browsersync and express seems a bit overkill in this case, why not just use node-http-proxy with the native http module?
var http = require('http')
var httpProxy = require('http-proxy')
var options = ...
var proxy = httpProxy.createProxyServer(options)
var server = http.createServer(function (req, res) {
var proxyUrl = getUrl()
proxy.web(req, res, { target: proxyUrl })
})
server.listen(8080, function () {
console.log('listening on *:8080')
})
As per me If you want SAAS service using proxy is not the good idea to go is what am thinking.. if you are going with proxy for each client will create process with new port... My Solution is to create node server with listen localhost and map *.domain.com to the server..
If you are using individual database for each client :-
in node logic get cname from request host and use that reference to connect database.
Final Controller code would be..
var express = require('express');
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
/* GET home page. */
router.get('/', function(req, res, next) {
var client = req.subdomains[0];
console.log(client);
MongoClient.connect('mongodb://localhost:27017/'+client, function(err, db) {
if (err) {
throw err;
}
db.collection('app1').find().toArray(function(err, result) {
if (err) {
throw err;
}
console.log('data');
console.log(result);
});
});
res.render('index', { title: 'Express' });
});
module.exports = router;
~
~
In future if you get more clients you can implement node cluster or standard Ubuntu cluster using webservice

nodejs auto refresh view after database updates

I would like use nodeJS to refresh my view, every time a function has made changes to the database. If we take MEAN-stack as an example, I don't want to send an $http-request every x seconds to check if changes have been made to the database. I would like the front end to get notified automatically and then update the view.
What are best practices for this? I would use some kind of Oberserver pattern in the server side, but do not know how I could notify the front end with that.
To get the front end to get notified automatically and then update the view you could use Socket.io framework.
You can find all of the documentation on their site: http://socket.io/
And here is a basic example:
app.js ( to set up the server)
var http = require('http');
var express = require('express');
var port = normalizePort(process.env.PORT || '1000');
var app = express();
var server = http.createServer(app);
server.listen(port);
io = require('socket.io')(server);
///ROUTES
var routes = require('./routes/index')(io);
var users = require('./routes/users');
///////
I pass the io object to route index(and ofcourse there is a lot more stuff on app.js..this is just a basic example...).
mysql.js (to create a pool for connections)
var mysql = require("mysql");
var pool = mysql.createPool({
host : 'host',
user : 'user',
password : 'pass',
database : 'db_name',
connectionLimit: 1000
});
exports.pool = pool;
index.js
module.exports = function(io) {
var express = require('express');
var router = express.Router();
var mysql = require('../mysql.js').pool;
io.on('connection', function (socket) {
socket.on('event_name', function (data) {
mysql.getConnection(function(err,connection){
if (err) {
connection.release();
return;
}
connection.query("SQL STUFF",function(err,rows){
if(rows.length>0){//checks if there are more than 0 rows returned.....
socket.emit('do_something',data_you_want_to_pass);
}
else{
socket.emit('do_something_else',data_you_want_to_pass);
}
connection.release();
});
connection.on('error', function(err) {
return;
});
});
});
});
router.get('/', function(req, res) {
res.render("index");
});
return router;
}
And then on html page you have socket.emit and socket.on again.....
I recommend you take a look at the documentation and a few other examples...
I hope I helped you.

socket.io not working node.js

I am not able to run socket.io code in node.js, console.log() is also not displaying when running the code. Below is the code.
app.js
var express = require('express');
var http = require('http');
var app = express();
app.set('port', process.env.PORT || 3000);
app.post('/testStream',test.testStream);
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
module.exports.appServer = server;
and I have created a test.js file where I am accessing this exported variable appServer.
var server = require('../app.js');
exports.testStream = function(req,res){
var io = require('socket.io').listen(server.appServer);
io.on('connection',function(socket){
console.log("in socket");
fs.readFile('E:/temp/testimg.png',function(err,buf){
socket.emit('image',{image: true,buffer: buf});
console.log("test image");
});
})
}
when the code runs it stucks and not showing the console.logs(). What I am doing wrong over here. Any help is very much appreciated.
I would suggest following the code structure as suggested in socket.io docs.
Also, you should not be calling io.listen or io.on('connection') inside your testStream express middleware. These are things you should only be doing once, and ideally they should happen during startup, inside app.js and not in reaction to a POST request. In fact, I'm not sure what the purpose of your testStream middleware is, its not even returning any response (eg res.end())
If you want to handle socket connections in a separate module you can, but instead of exporting your app's server the way you are, try passing the io instance as variable to your submodule. In short, try this:
app.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var test = require('./test')(io);
app.set('port', process.env.PORT || 3000);
server.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
test.js
module.exports = function(io) {
io.on('connection', function(socket) {
console.log("in socket");
fs.readFile('E:/temp/testimg.png', function(err, buf) {
socket.emit('image', {
image: true,
buffer: buf
});
console.log("test image");
});
});
};

how to add to add socket.io subscribers in node.js without rerunning setup code

Now edited with solution
I'm writing a web page, backed by Node and Express, which uses the twitter streaming API to plot the location of tweets containing a given word onto a Google map. The page connects to the server and places each tweet with location that the server emits onto the map.
the node js application is this. twitFactory just gives me a twitter object from the Twitter npm module with my various connection strings.
'use strict';
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var twitFactory = require('./lib/twitFactory');
var twit = twitFactory.twit();
var searchTerm = process.argv[2];
var locations = '-180,-90,180,90';
server.listen(3000);
app.use('/bower_components', express.static(__dirname + '/bower_components'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
twit.stream('filter', {locations: locations}, function (stream) {
stream.on('data', function (tweet) {
if (tweet.text && tweet.text.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1) {
if (tweet.text && tweet.coordinates && tweet.coordinates.coordinates && tweet.coordinates.type === 'Point') {
socket.emit('tweet', { text: tweet.text, lon: tweet.coordinates.coordinates[0], lat: tweet.coordinates.coordinates[1] });
}
}
});
});
});
I have this working for a single web client, which is fine for my development environment, but I want to avoid re-initialising the Twitter connection inside the on connection event every time a new client connects, or I would quickly hit my API call limit.
I think I want to define the twitter stream separately, and then add new connections to the socket's subscribers, but can't work out how to code this, without the nested structure you see above.
(I realise that it's very inefficient to get all tweets with location then filter by content, but very few tweets have location attached, and the API does not currently let you specify location AND search term, it gives you all tweets with either.)
UPDATE:
I found a solution which was to use a different Twitter Node module which allows the stream object and events to be declared separately. it's twit (as opposed to twitter) in npm. the code now looks like this:
'use strict';
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var logger = require('./lib/logger');
var twitFactory = require('./lib/twitFactory');
var searchTerm = process.argv[2];
var locations = ['-180','-90','180','90'];
var twit = twitFactory.twit();
var tweetStream = twit.stream('statuses/filter', {locations: locations});
server.listen(3000);
app.use('/bower_components', express.static(__dirname + '/bower_components'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
console.log('new connection');
tweetStream.on('tweet', function (tweet) {
if (tweet.text && tweet.text.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1) {
if (tweet.text && tweet.coordinates && tweet.coordinates.coordinates && tweet.coordinates.type === 'Point') {
socket.emit('tweet', { text: tweet.text, lon: tweet.coordinates.coordinates[0], lat: tweet.coordinates.coordinates[1] });
}
}
});
});

Resources