Can not connect socket.io to express4 - express

My app.js file looks like
let express = require('express');
let path = require('path');
let favicon = require('serve-favicon');
let logger = require('morgan');
let cookieParser = require('cookie-parser');
let bodyParser = require('body-parser');
let dotEnv = require('dotenv');
let helmet = require('helmet');
let compression = require('compression');
let passport = require('passport');
let socket_io = require("socket.io");
let app = express();
let io = socket_io();
app.io = io;
require('./server/config/socket')(io);
let useragent = require('express-useragent');
let cors = require('cors');
dotEnv.load();
require('./server/authentication/passport.local');
app.set('views', path.join(__dirname, 'server/views'));
app.set('view engine', 'jade');
app.set('view engine', 'ejs');
app.use(cors());
//app.use(logger('dev'));
app.use(helmet());
app.use(useragent.express());
app.use(compression())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(passport.initialize());
app.use(express.static(path.join(__dirname, 'public')));
/**
* Custom middle ware functions
*/
require('./server/middleware/authentication-middleware')(app);
require('./server/config/database')(app, process.env.NODE_ENV);
require('./server/routes')(app);
require('./server/middleware/custom-middleware')(app);
module.exports = app;
www file
let server = http.createServer(app);
let io = app.io;
io.attach(server);
socket.is file
module.exports = function(io) {
io.on('connection', function(socket) {
console.log('Socket.io is connected');
});
}
I have tried so many ways, but it does not fire the connection message. Does anyone here help me what is going wrong?
package.json file
expressjs : 4.16.0
socket.io : 2.0.4
Meanwhile, I have tried some other instruction, but does not work: https://onedesigncompany.com/news/express-generator-and-socket-io
Thanks in advance

In client side you can use socket.io-client
let socket = ClientSocket({ transports: ['websocket'] });
socket.on('connection',()=>{
console.log("")
})
And then at server(Considering that you have server instance.)
var socketIo = require("socket.io");
var io = socketIo.listen(server.listener);
io.on('connection', function (socketInstance) {
console.log("connected to server");
})

You might have to pass io to your routes to make it available:
require('./server/routes')(app, io);
Or use with Express Router:
const yourSpecificRoute = require('./server/youRoutes)(io);
const router = express.Router();
router.use('/route', yourSpecificRoute);

Related

Switching from working node js socket io serialport to node express router how to?

I am new to node express (started with node long time ago but didn't do much) and I would like to learn how to use it. I am going through some of my older work and reading lots of tutorials but I just can't seem to get this one working.
I have this app that reads data from some sensors on serial port and sends it to sesors.ejs. I would like to reprogram it in express. I have the sensor reading in terminal but not in ejs.
old (working) app.js
var http = require('http');
var fs = require('fs');
var url = require('url');
var path = require('path');
const { SerialPort } = require('serialport')
const { ByteLengthParser } = require('#serialport/parser-byte-length')
const port = new SerialPort({ path: 'COM4', baudRate: 9600 })
const parser = port.pipe(new ByteLengthParser({ length: 30 }))
var sensors = fs.readFileSync('views/sensors.ejs');
var app = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type':'text/html'});
res.end(sensors);
});
var io = require('socket.io').listen(app);
io.on('connection', function(data){
console.log
});
parser.on('data', function(data){
console.log(data.toString("UTF8"));
io.emit('data', data.toString("UTF8"))
});
app.listen(3000);
old (working) sensors.ejs
<script>
var socket = io();
socket.on('data', function(data){...}
</script>
This works great.
I went through several express routing tutorials but I don't know how to send io data to router.
I have c/p most of the code from old app.js to new sensor.js in routes dir, without fs, app.listen etc. I have c/p sensors.ejs to views folder.
In new app.js I have:
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var sensorsRouter = require('./routes/senzori');
var app = express();
app.set('views', path.join(\__dirname, 'views'));
app.set('view engine', 'ejs');
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);
app.use('/senzori', sensorsRouter);
index.ejs and users.ejs (fetch mysql data) are working (express is installed and working)
Thanks
I have found the solution. If anyone else with my level of "knowledge" needs the solution, here it is:
I have moved reading serial port to bin/www
The only code in sensors.js is:
router.get('/', function(req, res, next) {
res.render('sensors');
});

authenticate tp express server tunneled through ngrok

I have an express server serving react pages. I am trying to show the work to a client via a ngrok tunnel. But whenever I try to log in at the ngrok URL for my server it fails to connect back to my localhost where the express routes for auth are.
I feel like it's a simple error I'm making. The browser is trying to make a request to the express server at localhost:5000, but there is nothing at localhost on my client's network.
This is my app.js
const createError = require('http-errors');
const express = require('express');
const debug = require('debug')('app');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
require('dotenv').config()
const ensureToken = require('./middleware/ensureToken');
const path = require('path');
const app = express();
const { init } = require('./utils/cron/createCron');
const cors = require('cors')
// Routers
const authRouter = require('./routes/auth')
const botRouter = require('./routes/bot')
const proxyRouter = require('./routes/proxy');
const winstonLogger = require('./utils/log/logger');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
const whiteList = ['http://localhost:3000/', 'http://localhost:3000']
const corsOptions = {
origin: (origin, callback)=>{
if (whiteList.indexOf(origin) !== -1){
callback(null, true)
}else{
callback(new Error('Not Allowed by CORS'))
}
optionsSuccessStatus:200
}
}
// app.use(cors(corsOptions))
app.use(cors({ credentials: true, origin: true }))
app.use(express.static(path.join(__dirname, 'build')));
// Base Routes
app.use('/api/auth', authRouter);
app.use(ensureToken) //Add this before routes that need to be protected ny valid token
app.use('/api/bot', botRouter);
app.use('/api/proxy', proxyRouter);
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
// 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');
});
app.listen(process.env.PORT, ()=>{
winstonLogger.info(`Listening on ${process.env.PORT}`)
debug(`Listening on ${process.env.PORT}`);
console.log(`Listening on ${process.env.PORT}`);
init()
})
module.exports = app;
Any help is appreciated!!

express routes not working - returning 404 error

I'm trying to set up a simple express project, and backend will be purely for api and frontend will be vue. I tried adding an api router, and not only does it not work, but even the root page doesn't work. I've not coded in express for a very long time, and wondering if some one could guide me on what's the problem? The error message is 404 NotFoundError: Not Found.
I'm navigating to localhost:3000, and I can see the call on the terminal, so port should be correct too?
/src/api/urls.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('Just a test');
});
module.exports = router;
I didn't change the folder structure/naming for the original routes/index.js.
/src/routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('Just a test');
});
module.exports = router;
And for the main file
/src/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 indexRouter = require('./routes/index');
var apiRouter = require('./api/urls');
var app = express();
app.use(require('connect-history-api-fallback')());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
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('/api', apiRouter);
// 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;
All good except endpoint url that should be with middleware function only. Modifying these should work,
/src/api/urls.js
var express = require('express');
var router = express.Router();
router.get('/api/test', function(req, res) {
res.send('Just a test');
});
module.exports = router;
/src/routes/index.js
var express = require('express');
var router = express.Router();
router.get('/api/test2', function(req, res) {
res.send('Just a test');
});
module.exports = router;
In app.js you should register your routes as,
// Routes
app.use([
require('./src/api/urls'),
require('./src/routes/index'),
]);
Access by url ( http://<yourhost>/api/test1 )

app.js code comparison because ejs not working

I'm using express.js and ejs.
I will post below two codes for the app.js file. The thing is that ejs and layout.ejs do not work with the one of those two codes, but it works perfectly with the other
Here are the two codes:
The first one, which ejs is working:
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const path = require('path')
const app = express();
// Bodyparser
app.use(express.urlencoded({extended:false}));
/// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
//PUBLIC FOLDER(css and js)
app.use(express.static(path.join(__dirname,'/public')));
// Express body parser
app.use(express.urlencoded({ extended: true }));
// Routes
app.use('/', require('./routes/index.js'));
app.use('/users', require('./routes/users.js'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
and the second one, which ejs is not working:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 5000;
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const path = require('path')
// Bodyparser
app.use(express.urlencoded({extended:false}));
//ROUTES
app.use('/', require('./routes/index'))
app.use('/users', require('./routes/users'))
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.set('view options', { layout:'layout.ejs' });
//PUBLIC FOLDER(css and js)
app.use(express.static(path.join(__dirname,'/public')));
//DB CONFIG
const db = require('./config/keys').MongoURI;
// //Connect to mongo
mongoose.connect(db, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then( () => console.log('MongoDB Connected...'))
.catch( err => console.log(err));
app.listen(PORT, console.log(`Server started on PORT ${PORT}`));
I'm trying to figure out what's the issue with the second code and doesn't make the ejs work. Can anyone have a quick glimpse and compare these two and tell me what's the problem? Thank you for your time

express.js 4 and sockets with express router

I'm trying to create a really simple node API using express.js 4 but I need a few 'realtime' events for which I added socket.io. I'm fairly new to both so I'm likely missing something basic but I can't find good docs/tuts on this.
In the express app (created with the express generator) I have something like this based on simple examples and project docs that I read. This works OK and from client apps, I can send/receive the socket events:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// error handlers omitted
module.exports = app;
but I want to use the sockets from my API routes (in the ./routes/api.js file that I 'require' above). For example, someone might use the API to PUT/POST a resource and I want that broadcast to connected socket.io clients.
I cannot see how to use the 'io' variable or organise the code currently in the io.sockets.on('connection' ... function inside express routes. Here's the ./routes/api.js file:
var express = require('express');
var router = express.Router();
var io = ???;
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
io.sockets.emit('update', foo); // how?
});
module.exports = router;
One option is to pass it in to req object.
app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// Make io accessible to our router
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/api', api);
// error handlers omitted
module.exports = app;
./routes/api.js:
var express = require('express');
var router = express.Router();
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
req.io.sockets.emit('update', foo);
});
module.exports = router;
I've modified your files a little bit, may you check if it works?
You can pass the io you've defined to your routes like below;
require('./routes/api')(app,io);
I didn't test the Socket.IO parts but there is no syntax error and routes also working.
server.js file:
var express = require('express');
var app = express();
var path = require('path');
var logger = require('morgan');
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
require('./routes/api')(app,io);
console.log("Server listening at port 3000");
api.js:
module.exports = function(app,io) {
app.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
console.log("PUT OK!");
io.sockets.emit('update'); // how?
res.json({result: "update sent over IO"});
});
}
Supposing you want to access the SocketIO from anywhere in your application, not just in the router, you could create a singleton for it. This is what works for me:
//socket-singletion.js
var socket = require('socket.io');
var SocketSingleton = (function() {
this.io = null;
this.configure = function(server) {
this.io = socket(server);
}
return this;
})();
module.exports = SocketSingleton;
Then, you need to configure it using your server:
//server config file
var SocketSingleton = require('./socket-singleton');
var http = require('http');
var server = http.createServer(app);
SocketSingleton.configure(server); // <--here
server.listen('3000');
Finally, use it wherever you want:
//router/index.js
var express = require('express');
var router = express.Router();
var SocketSingleton = require('../socket-singleton');
/* GET home page. */
router.get('/', function(req, res, next) {
setTimeout(function(){
SocketSingleton.io.emit('news', {msg: 'success!'});
}, 3000);
res.render('index', { title: 'Express' });
});
module.exports = router;
One more option is to use req.app.
app.js
const express = require('express');
const path = require('path');
const logger = require('morgan');
const api = require('./routes/api');
const app = express();
const io = require('socket.io').listen(app.listen(3000));
// Keep the io instance
app.io = io;
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
// ...
app.use('/api', api);
module.exports = app;
routes/api.js
const express = require('express');
const router = express.Router();
router.put('/foo', function(req, res) {
/*
* API
*/
// Broadcast the updated foo..
req.app.io.sockets.emit('update', foo);
});
module.exports = router;
Refactored Edudjr's answer.
Change the singleton to create a new instance of socket.io server
const { Server } = require('socket.io');
const singleton = (() => {
this.configure = (server) => this.io = new Server(server)
return this
})();
module.exports = singleton
Initialise your express app, the server and the singleton.
// initialise app
const app = express();
const server = require('http').createServer(app);
// configure socket.io
socket.configure(server)
Then in your router
const socket = require('/utils/socket-singleton');
socket.io.emit('event', {message: 'your message here'})
I think best way is to set io as a property of req, like below:
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/your-sub-link', your-router);