I created an express app in NodeJS using express --view=pug expressapp. It created an app.js file
app.js
var createError = require('http-errors');
...
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
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');
});
//socket setup
var socket = require('socket.io');
var io = socket(app);
io.on('connection', function(socket) {
console.log('made socket connection')
})
module.exports = app;
at the end I try to bind socket.io to app but it expects to bind to server like so
var server = app.listen(3000, function() {
});
//socket setup
var socket = require('socket.io');
var io = socket(server);
I also use nodemon so I run the app using nodemon expressapp and it runs on port 3000. However I can't find where the auto generated express files have setup the server. Because If i try like this
//socket setup
var socket = require('socket.io');
var server = app.listen(3000, function() {
});
var io = socket(server);
I get an error that port 3000 is already in use (by itself) I changed it to 4000 and it works.
Not ideal, if you know how to connect with port 3000 will appreciate the assist.
You shall find it under the directory bin/www
Related
I have built a webapp, based on wes bos's course:
https://github.com/wesbos/Learn-Node/tree/master/stepped-solutions/45%20-%20Finished%20App
Now, I want to add a simple messaging system, so I'm trying to add socket.io
On their website: https://socket.io/get-started/chat/ they suggest this code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
So in my start.js file I'm trying to adapt it to the code above, and it partly works, only that on their website it says it should only log once for every connected user.
And in my case it logs like every frame.
Any idea what is wrong?
This is my start.js
const app = require('./app');
app.set('port', process.env.PORT || 7777);
const server = app.listen(app.get('port'), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
// const http = require('http').Server(app);
const io = require('socket.io').listen(server);
io.on('connection', function(socket){
console.log('a user connected');
});
EDIT: Here is also my ap.js:
// create our Express app
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views')); // this is the folder where we keep our pug files
app.set('view engine', 'pug'); // we use the engine pug, mustache or EJS work great too
// serves up static files from the public folder. Anything in public/ will just be served up as the file it is
app.use(express.static(path.join(__dirname, 'public')));
// Takes the raw requests and turns them into usable properties on req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Exposes a bunch of methods for validating data. Used heavily on userController.validateRegister
app.use(expressValidator());
// populates req.cookies with any cookies that came along with the request
app.use(cookieParser());
// Sessions allow us to store data on visitors from request to request
// This keeps users logged in and allows us to send flash messages
app.use(session({
secret: process.env.SECRET,
key: process.env.KEY,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
// // Passport JS is what we use to handle our logins
app.use(passport.initialize());
app.use(passport.session());
// // The flash middleware let's us use req.flash('error', 'Shit!'), which will then pass that message to the next page the user requests
app.use(flash());
// pass variables to our templates + all requests
app.use((req, res, next) => {
res.locals.h = helpers;
res.locals.flashes = req.flash();
res.locals.user = req.user || null;
res.locals.currentPath = req.path;
next();
});
// promisify some callback based APIs
app.use((req, res, next) => {
req.login = promisify(req.login, req);
next();
});
// After allllll that above middleware, we finally handle our own routes!
app.use('/', routes);
// If that above routes didnt work, we 404 them and forward to error handler
app.use(errorHandlers.notFound);
// One of our error handlers will see if these errors are just validation errors
app.use(errorHandlers.flashValidationErrors);
// Otherwise this was a really bad error we didn't expect! Shoot eh
if (app.get('env') === 'development') {
/* Development Error Handler - Prints stack trace */
app.use(errorHandlers.developmentErrors);
}
// production error handler
app.use(errorHandlers.productionErrors);
// done! we export it so we can start the site in start.js
module.exports = app;
You need to remove the following line:
const server = app.listen(app.get('port'), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
You're listening here, but you should be doing this:
const http = require('http').Server(app);
http.listen(3000, function(){
console.log('listening on *:3000');
});
or with your case of setting the port through express:
const http = require('http').Server(app);
http.listen(app.get('port'), function(){
console.log(`Express running → PORT ${server.address().port}`);
});
A more common syntax is to declare you port as a const:
const PORT = 7777
const http = require('http').Server(app);
http.listen(PORT, function(){
console.log(`Express running → PORT ${PORT}`);
});
In turn, your socket.io server will be created as:
const io = require('socket.io')(http);
As it stands your are (from what I can tell) creating two servers.
EDIT:
Your entire start.js should look like this:
const app = require('./app');
app.set('port', process.env.PORT || 7777);
const http = require('http').Server(app);
const io = require('socket.io')(http)
io.on('connection', function(socket){
console.log('as user connected' + Math.random());
});
http.listen(app.get('port'), function(){
console.log(`Express running → PORT ${server.address().port}`);
});
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' });
});
I've searched and tried a lot of things, and I can't get my deployment to work.
My node.js app works locally, but doesn't work when deployed on heroku. The problem is the port I'm using, I believe.
In my app.js,I have:
1) a server+port:
var server = require('http').createServer();
var port = process.env.PORT || 5000;
2) The port I want to listen to: (I do think this part is wrong)
server.listen(port, function() {
console.log("Listening on " + port);
});
app.listen(port);
// app.listen(process.env.PORT || 5000);
module.exports = app;
3) And some other stuff
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
// 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(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(__dirname + '/'))
// var routes = require('./routes/index');
var routes = require('./routes/index')(passport);
var users = require('./routes/users');
// make db accessible to the router
app.use(function(req,res,next){
req.db = db;
next();
});
app.use('/', routes);
app.use('/users', users);
// app.use('/api', api);
// 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: {}
});
});
When I'm on my deployed app, and here you can see it says it will redirect to the place I want (at the bottom left)
the frozen-fortress.../login/facebook..etc
however, when i actually click on it, it gives me
localhost:3000/login/facebook...etc
This happens with some of my others links too, but NOT all the links.
What can I do the change the port? I have tried things like app.listen(port) as well.
Thank you in advance! (Also I apologize if the format of my question looks funky, this is my first time on stackoverflow).
I might be wrong, but
look at this part of code:
var server = require('http').createServer();
var port = process.env.PORT || 5000;
// ...
server.listen(port, function() {
console.log("Listening on " + port);
});
app.listen(port);
You create two servers here: server and Express' app. Both will try to listen on the same port and one of them will fail. I mean, Express already has http server inside, you don't need another one:
var port = process.env.PORT || 5000;
app = express()
app.listen(port)
app.use(...)
app.get('/', function(...){
// there you go
})
Here's doc about listen() and other Express things
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 having problem with setting socketIO 1.1 up to work on Heroku. I'm running Express v4.2. The socketio runs perfectly on localhost. However, on Heroku, it gives this error:
From Heroku log:
2014-09-15T09:40:14.578660+00:00 app[web.1]: GET /socket.io/?EIO=3&transport=polling&t=1410774014583-86 404 6ms - 744b
From browser:
GET http://[mydomainname]/socket.io/?EIO=3&transport=polling&t=1410774080589-97 404 (Not Found) socket.io.js:2680Request.create socket.io.js:2680Request socket.io.js:2614XHR.request socket.io.js:2555XHR.doPoll socket.io.js:2585Polling.poll socket.io.js:2951Polling.doOpen socket.io.js:2895Transport.open socket.io.js:2106Socket.open socket.io.js:1580Socket socket.io.js:1467Socket socket.io.js:1419Manager.open.Manager.connect socket.io.js:272(anonymous function)
I have followed the recommended configurations in Socket IO documentations. Relevant code as follows:
var express = require('express');
/* routes */
var routes = require('./routes/index');
var users = require('./routes/users');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var cons = require('consolidate');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('dust', cons.dust);
app.set('view engine', 'dust');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser('hashionhashion'));
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
//routing
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: {}
});
});
//start the server
var server = require('http').Server(app);
var io = require('socket.io').listen(server);
var ioSockets = {};
io.on('connection', function(socket) {
ioSockets[socket.id] = socket;
socket.emit('welcome', {message: socket.id});
socket.on('disconnect', function(socket) {
delete ioSockets[socket.id];
});
});
exports.ioSockets = ioSockets;
module.exports = app;
server.listen(3000, function() {
console.log('Congrats, nothing broke!! Listening on port %d', server.address().port);
});
In my client file, the script are as follows:
<script src="my_path_to/socket.io.js"></script>
<script>
var socket = io.connect();
var socketId = '';
socket.on('welcome', function (data) {
socketId = data.message;
});
</script>
I also tried io.connect to "http://localhost", "http://localhost:3000", and my Heroku app domain. All of them produces the same error.
Any help will be greatly appreciated!
The issue ends up to be a express one, which has since been corrected in versions after 4.10.0.
For your own reading:
https://github.com/strongloop/express/issues/2406
https://github.com/jshttp/on-finished/issues/10
Look like you change socket.io path. Because I saw src="my_path_to/socket.io.js". socket.io try to connect but got 404.
Is there a route of express handled '/socket.io/'?
Even you resolve the 404 error. You will hit the other error. Because currently on heroku you must set socket.io connect to a https address. Otherwise socket.io will work under polling.
More detail:
https://github.com/Automattic/engine.io/issues/261