404 error with express and express-ws - node.js

I'm having trouble trying to figure out why I'm getting this 404 error. I've gone through all the other questions on this site that cover 'express-ws' and i've modeled my code exactly how the solutions prescribed yet the websocket won't make a connection. I'm trying to create a websocket connection between my express server and react app. Below are previews of my code:
Express using express-ws (server.js):
var express = require('express');
var expressWs = require('express-ws');
var bodyParser = require('body-parser');
var cors = require('cors');
var nodemailer = require('nodemailer');
var email = require('./credentials');
var port = process.env.PORT || 3001;
var path = require('path');
// const WebSocket = require('ws');
// const http = require('http');
expressWs = expressWs(express());
let app = expressWs.app;
var server = require('http').createServer(app);
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
if (process.env.NODE_ENV === 'production') {
app.use(express.static('app/build'));
}
app.get('/', function(req, res){
console.log('server running!');
res.end();
});
app.ws('/ws', function(ws, req) {
console.log( 'socket running!' );
});
server.listen(port);
console.log('server started on port ' + port);
The GET route works fine but the ws route doesn't.
Call to express from React app:
componentDidMount() {
let ws = new WebSocket('ws://localhost:3001/ws');
ws.on( 'open', function open() {
console.log('app connected to websocket!');
} );
ws.on( 'message', function ( message ) {
console.log( message );
})
}
I've looked at all the following questions and don't understand why their solutions don't work for me:
Socket.IO 404 Error
express-ws connection problem
Node not working with express-ws
If anyone can let me know what's going on that would be great.

It seems your code does not follow express-ws's document. To use express-ws and make WebSocket endpoint, the code would be as:
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
...
app.ws('/', function(ws, req) {
ws.on('message', function(msg) {
console.log(msg);
});
console.log('socket running');
});
app.listen(3000);
In the client side, ws object does not have field on. To listen WebSocket connection and message, you can use onopen and onmessage:
ws.onopen = function() {
console.log('app connected to websocket!');
};
ws.onmessage = function(message) {
console.log( message );
};

I had this exact problem and for me the solution was to change:
server.listen(port);
to:
app.listen(port);
I suspect what is going on is that express-ws is using the app listen function as its cue to start upgrading connections to ws and this won't happen if the server listen port occurs instead.

Related

Express server and socket.io not working in same port

Not working can't find any issue in code##
If I put any port number instead of server it's working but why didn't it's working with socket server anyone explain
I tried some solution but none of them work I want to run socket.io and express on same port number
const express = require('express');
const cors = require("cors");
const socketIO = require('socket.io');
const http = require('http');
const app = express();
const server = http.createServer(app);
const passport = require("passport");
const authRoute = require('./routes/auth');
const userRoute = require('./routes/user');
const PORT = process.env.PORT || 9000;
const db = require('./config/mongoose');
app.use(express.json());
app.use(cors());
app.use(passport.initialize());
require("./config/passport")(passport);
app.use(express.json());
app.use("/api/auth", authRoute);
app.use("/api/user", passport.authenticate('jwt', { session: false }),userRoute);
if(process.env.NODE_ENV === 'production')
{
app.use(express.static('client/build'))
}
Here is the issue if I switch server to any port number it's fine
const io = socketIO(server, {
cors: {
origin: '*',
}
});
let state = {};
io.on("connection", (socket) => {
const { id } = socket.client;
socket.on('disconnect', function () {
console.log('socket disconnected!');
});
socket.on('join_room', function (data) {
console.log('joining request rec.', data);
socket.join(data.room);
io.in(data.room).emit('user_joined', data);
});
socket.on('send_code', function (data) {
io.in(data.room).emit('receive_code', data);
});
});
app.listen(PORT, function (err) {
if(err){
console.log(err);
return;
}
console.log(`Server is up and running on port: ${PORT}`);
});
http.createServer(app) and app.listen() are not compatible as they both try to do the same thing. If you look at the source code for app.listen(), you will see this:
app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
So, it's creating a DIFFERENT server object. You end up with two and the first one never gets started so when you give it to socket.io, it never works.
Instead, remove this:
const server = http.createServer(app);
And, use this instead:
const server = app.listen(PORT, function (err) { ...});
This way, your server variable will contain the one and only server object that is actually running.
Alternatively, you could remove the app.listen() and then just add this in it's place:
server.listen(PORT, ...);
The general idea is that you want this pair:
const server = http.createServer(app);
server.listen(PORT, ...);
Or, just this:
const server = app.listen(PORT, ...);
You cannot use both. Either way, that server object will represent the server that is actually running and will work with socket.io.

Socket.io double connection with only one client

I am writing this server app (express and socket.io), just at the beginning.
I see double log, so I have double connection to server when starting a tab at localhost:8080.
What am I doing wrong? Is this a Socket.io bug?
const express = require("express");
const path = require("path");
const socket = require("socket.io");
const port = process.env.PORT || 8080;
const app = express();
const server = app.listen(port);
app.use(express.static(__dirname + "/dist"));
app.get("/", (req, res) => {
res.sendFile(path.resolve(__dirname + "/dist", "index.html"));
});
// Socket setup
const io = socket(server);
io.on("connect", function (socket) {
console.log("Made socket connection");
});
The problem was that more js client files were calling socket().
Right method is to import socket.io library in , into your html file, so that this will be available to all js client file, implementing only one connection.

Issue to add socketio to API Express

i'm trying to add socket.io on my already existing NodeJS API REST Project.
var express = require('express')
var bodyParser = require('body-parser');
var https = require('https');
var http = require('http');
var fs = require('fs');
var router = require('./route/router');
require('dotenv').config();
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(require('helmet')());
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Authorization,Content-Type');
next();
});
router(app);
if (process.env.PRODUCTION === "false") {
http.createServer(app).listen(8080, function() {
console.log('8080 ok');
});
var io = require('socket.io')(http);
} else {
const options = {
cert: fs.readFileSync('./../../etc/letsencrypt/live/test.com/fullchain.pem'),
key: fs.readFileSync('./../../etc/letsencrypt/live/test.com/privkey.pem')
};
https.createServer(options, app).listen(8443, function() {
console.log('8443 ok');
});
var io = require('socket.io')(https);
}
io.sockets.on('connection', socket => {
console.log('socketio connected');
});
I have no error displayed (server side). But, when I tried on client side, this.socket = io('ws://localhost:8080/');, it's not working at all.
I get GEThttp://localhost:8080/socket.io/?EIO=3&transport=polling&t=NG6_U6i [HTTP/1.1 404 Not Found 1ms] browser console.
It seems that something is not ok with the server, but I can't find what's going on
Any idea ?
Thanks
Try this way, you need to include (I don't know if this is the correct word to use) the express server into the socket.io server.
const express = require('express');
const socketio = require('socket.io');
const port = process.env.PORT || 3006;
const app = express();
const server = app.listen(port, () => {
console.log(`App started on port ${port}`)
});
const io = socketio(server, { forceNew: true });
io.on('connect', (socket) => {
// do this
// do that
});
The code above is a skeleton of how express and socket.io are used together. Please modify it as per your needs.
Good luck.

SocketIO emit won't fire inside express route

The following works fine, I can get the http response on my client app BUT the socketio emit doesn't seem to work. I have no idea why it is not firing.
Here's my code (some parts removed):
app.js
var express = require('express');
var port = process.env.PORT || 3000;
var socketio = require('socket.io');
var app = express();
var server = require('http').Server(app);
var io = socketio(server);
var beacons = require('./routes/beacons')(io);
app.use('/beacons', beacons);
server.listen(port, () => {
console.log('Listening on port '+port);
});
io.on('connection', (socket) => {
socket.on('beacon:show', function(data) {
console.log('Show beacon: ' + data)
socket.broadcast.emit('beacon:draw', data)
})
});
module.exports = app;
beacons.js
var express = require('express');
var router = express.Router();
module.exports = function(io) {
router.get('/buy', function(req, res) {
io.emit('beacon:show', {data: someData}) // Not Firing
res.json({success: true})
})
return router
}
You need to wrap your io.emit() inside an io.on('connection', => {}).
At the moment, you are sending in just the io variable, but every single request and emission needs to be wrapped inside a connection event. Otherwise how does socket.io know who it's sending it to, or if there's even anyone to send it to?
This can only really be done inside beacons.js and the router.get('/buy') section, because having it the other way around (a route wrapped inside a connection) won't work.

Cannot access Mosca mqtt broker deployed on Heroku

const express = require('express');
const helmet = require('helmet');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const path = require('path');
const server = require('./modules/server');
const dashboard = require('./modules/dashboard');
const config = require('./config');
const routes = require('./routes');
const app = express();
app.use(helmet()); // secure http communication middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('tiny')); // http request logger
app.use('/', routes);
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
const mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, server);
app.use('/dashboard', dashboard);
/**
* Mosca Server Settings below
*/
var mosca = require('mosca');
var http = require('http');
var httpServer = http.createServer(app);
var moscaSettingss = {
type: 'mongo',
url: 'mongodb://***:31157/mqtt',
pubsubCollection: 'pub_sub',
mongo: {}
};
httpServer= new mosca.Server({
backend: moscaSettingss,
persistence: {
factory: mosca.persistence.Mongo,
url: 'mongodb://***:31157/mqtt'
}
}, function() {
httpServer.attachHttpServer(app);
});
httpServer.on('ready', function() {
console.log('Mosca is running');
});
httpServer.on('clientConnected', function(client) {
console.log('client connected', client.id);
});
httpServer.on('published', function(packet, client) {
console.log('Published : ', packet.payload);
});
httpServer.on('subscribed', function(topic, client) {
console.log('subscribed : ', topic);
});
httpServer.on('unsubscribed', function(topic, client) {
console.log('unsubscribed : ', topic);
});
httpServer.on('clientDisconnecting', function(client) {
console.log('clientDisconnecting : ', client.id);
});
httpServer.on('clientDisconnected', function(client) {
console.log('clientDisconnected : ', client.id);
});
/**
* End of Mosca Server Settings
*/
app.listen(config.server.port, () => {
console.log(`Magic happens on port ${config.server.port}`);
});
module.exports = app;
I have made an express app, which contains mosca mqtt broker. Some how I cannot connect to that mqtt. Tried all possible urls.
In the express app, I made a mqtt client, which sucessfully connects with the broker. But out side Heroku, my devices are unable to connect.
Awaiting response.
Heroku will not open the port necessary for MQTT. This is why express can access it locally but none of your devices can.
I also try ws://mevris-cloud.herokuapp.com:80. It works!

Resources