I am building an application on node.js using Express. My application is running on port 3001. I want to set virtual host for my application so that when I use http://local.com:3001, it should lead me to my application's home page.
My node version is : v0.12.3
Express version : 4.12.4
NPM version : 2.9.1
I have added the host in /etc/hosts.
My application is at /var/www/local. I set up an express app under /var/www/vhost to act as vhost manager.After a lot of research, I tried using below two methods but none of them worked:
1) app.js of /var/www/vhost
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var vhost = require('vhost');
var app = express();
var main = express();
if (!module.parent) main.use(logger('dev'));
main.get('/', function(req, res){
res.send('Hello from main app!');
});
main.get('/:sub', function(req, res){
res.send('requested ' + req.params.sub);
});
// Redirect app
var redirect = express();
redirect.use(function(req, res){
if (!module.parent) console.log(req.vhost);
res.redirect('http://local.com:3001/' + req.vhost[0]);
});
// Vhost app
var app = module.exports = express();
app.use(vhost('*.local.com', redirect)); // Serves all subdomains via Redirect app
app.use(vhost('local.com', main)); // Serves top level domain via Main server app
if (!module.parent) {
app.listen(3001);
console.log('Express started on port 3001');
}
2) app.js of /var/www/vhost using express-vhost
var evh = require('express-vhost'),
express = require('express');
var appFactory = function(echo) {
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
return app;
};
var server = express();
server.use(evh.vhost(server.enabled('trust proxy')));
server.listen(3006);
evh.register('http://local.com:3001', appFactory('/var/www/local/app.js'));
Any suggestions if I am doing something wrong here or is there any other way to achieve the concept of virtual hosting with express on node.js would be really helpful. Thanks in advance :)
Related
I am working on a Nodejs Web application project which is based on Express Framework. I am working on creating a Sign up page. After giving the username and password the url should be redirected to profile page. In the views folder I created a file "profile.hbs". But the profile is not being recognized and I getting 404 not found. Please share your ideas on how to debug this issue.Thanks in advance.
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var expressHbs=require('express-handlebars');
var mongoose=require('mongoose');
var session=require('express-session');
var passport=require('passport');
var flash=require('connect-flash');
const mocha=require('mocha');
var validator=require('express-validator');
var indexRouter = require('./routes/index');
//var usersRouter = require('./routes/users');
var app = express();
mongoose.connect('mongodb://localhost:27017/shopping');
require('./config/passport');
// view engine setup
app.engine('.hbs',expressHbs({defaultLayout:'layout',extname:'.hbs'}));
app.set('view engine', '.hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(validator());
app.use(cookieParser());
app.use(session({secret:'mysupersecret',resave:false,saveUninitialized:false}));
app.use(passport.initialize());
app.use(flash());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
//app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Routing file
var express = require('express');
var router = express.Router();
var csrf=require('csurf');
var passport=require('passport');
const canine= require('../models/dogfood');
var csrfProtection=csrf();
router.use(csrfProtection);
/* GET home page. */
router.get('/', function(req, res, next) {
canine.find(function(err,docs){
var productChunks=[];
var chunkSize=3;
for(var i=0;i<docs.length;i += chunkSize){
productChunks.push(docs.slice(i,i+chunkSize));
}
res.render('shop/index', { title: 'Express',diets:productChunks});
});
});
router.get('/user/signup',function(req,res,next){
res.render('user/signup',{csrfToken:req.csrfToken()})
});
router.post('user/signup',passport.authenticate('local.signup',{
successRedirect:'user/profile',
failureRedirect:'user/signup',
failureFlash:true
}));
router.get('user/profile',function(req,res,next) {
res.render('user/profile');
});
module.exports = router;
You have a typo in the route name. It should be '/user/profile'
router.get('/user/profile', function(req,res,next) ...
Im using node js with express framework and socket.io in my project.
when i load test page in browser(with this address: http://localhost:3001/test) every thing is fine and print "a user connected" in server log but when i refresh page again print that message two time and with another refresh print that message three times and with every refresh repeat that message.
whats wrong in my code ?
thanks.
test.js
var express = require('express');
var router = express.Router();
var io = require('../app');
router.get('/', function(req, res, next) {
io.on('connection', function(socket){
console.log('a user connected');
});
res.render('test', { title: 'test' });
});
module.exports = router;
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var session = require('express-session')
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(3001);
module.exports = io;
var index = require('./routes/index');
var users = require('./routes/users');
var test = require('./routes/test');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
app.use('/test', test);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
You are adding an additional event handler on every GET / request.
You only need to add the event handler once, outside of a http route. Think of it as the socketio equivalent of a route.
var io = require('socket.io')(server);
io.on('connection', function(socket){
console.log('a user connected');
});
Then in your router, just deal with the http request
router.get('/', function(req, res, next) {
res.render('test', { title: 'test' });
});
My application works when i specify a port number to socket.io that is diffrent from the server port number. The working code goes as follows:
This is my app.js file:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var configDB = require('./config/database.js');
var session = require('express-session');
var passport = require('passport');
var routes = require('./routes/index');
var auth = require('./routes/auth.js');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.set(process.env.PORT || 1337);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret: 'mysessionsecret' }));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect(configDB.url);
app.use('/', routes);
app.use('/auth', auth);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var talk = require('./socket/talk.js')(app);
module.exports = app;
This is my talk.js file:
var init = function (app){
var server = require("http").createServer(app).listen(3000);
var io = require("socket.io").listen(server);
var socketioJwt = require("socketio-jwt");
var jwtSecret = require('../config/jwtSecret');
console.log("init");
io.set("authorization", socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
io.sockets.on("connection", function (socket) {
console.log("connected");
socket.on("send", function (data) {
console.log(data);
var username = data.username;
var message = data.message;
var datetime = data.datetime;
socket.broadcast.emit("send", data);
});
socket.on("busy", function () {
socket.emit("busy");
socket.broadcast.emit("busy");
});
socket.on("free", function () {
socket.emit("free");
socket.broadcast.emit("free");
});
});
}
module.exports = init;
This is my script tag in index.ejs:
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
And finally this is my io connect from the client:
socket = io("http://localhost:3000/",{
query: 'token=' + tok
});
This works but the problem is that i want to publish my site to Azure but it is not possible to let a Azure website listen to diffrent ports. At least i think it is not possible.
One of the many things I tried is changing the talk.js file to this:
var init = function (app){
var server = require("http").createServer(app).listen(app.get('port'));
var io = require("socket.io").listen(server);
...
But i it doesn't work. I always get something along the lines of http://localhost/socket.io/socket.io.js not found
If i change the script tag in my index.ejs file to this
<script src="http://cdn.socket.io/socket.io-1.2.1.js"></script>
The socket.io.js file gets loaded but when i connect form te client side i get a continious 404 not found error.
I looked at a lot of solutions online but none of them work. I really don't know what i am doing wrong.
This error comes from the bin/www.js file being called before app.js when using npm start. A quick solution is to bypass www.js, which is only used to handle some common errors, as it is suggested in this answer.
This github repo is an implementation of this solution and can be used as a starting point for any Express.js + socket.io application.
I am trying to create an Express app with Socket.IO. It seems like Express has changed quite a lot and most of the code online about getting the 2 to work together is out of date. This is what I have:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io').listen(http);
io.on('connection', function(socket){
console.log('a user connected');
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
The server starts ok and says
info - socket.io started
However the front-end has a 404 error on http://example.com:3000/socket.io/socket.io.js
edit
If I add
http.listen(8080);
The server runs twice on port 3000 and 8080, the 3000 version does not load socket.io.js and the 8080 version does. How can I have it so the server is only running on 3000? changing it to 3000 errors and it tries to listen twice
The answer was to make the changes in bin/www.js instead of app.js
#!/usr/bin/env node
var debug = require('debug')('test1');
var app = require('../app');
app.set('port', process.env.PORT || 3000);
var http = require('http').Server(app);
var io = require('socket.io')(http);
var server = http.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
Change the io include to:
var io = require('socket.io')(http);
And towards the bottom add something like:
http.listen(3000, function() {
console.log('Listening on port %d', http.address().port);
});
I am trying to add an "about" page to my new express app.
I am running express 4 with handlebars (hbs).
I have read through a number of tutorials but most don't go into adding a new route (or do but don't explain very well) I have been working from this tutorial primarily.
I need to know what to add to my app.js and my routes/ folder, I have about.hbs ready in views.
here is my app.js (generated by express generator):
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
and my routes/ folder contains index.js and users.js.
index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
module.exports = router;
Sorry for simplicity of question, but I have spent 3 hours on this already and I feelit is probably a fairly easy thing to do.
I suggest you ditch the general default express generated application and create a proper routing system. Your app.js file should not contain routing, only environment variables. Here is the way I've setup my projects:
App.js
var express = require('express');
var http = require('http');
var path = require('path');
var compression = require('compression');
var app = module.exports = express();
var cacheTime = 86400000*7; //a week
//all environments
app.use(compression());
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.engine('html', require('hogan-express'));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public',{ maxAge: cacheTime }));
//development only
if ('development' === app.get('env')) {
app.use(express.errorHandler());
}
require('./routes/index.js');
http.createServer(app).listen(app.get('port'), function(req,res){
console.log('Express server listening on port ' + app.get('port'));
});
The routes file:
var app = require('../app.js');
app.get('/Contact', function(req, res) {
res.render('contact.html', { /*object*/ });
});
//continue routes here
It's scalable and a viable option for large company projects. You may also split up the routes file into sepererate sections to organize better. Note: You will need to change some of my settings to your liking