Socket.io + nodejs = Error during WebSocket handshake: Unexpected response code: 500 - node.js

I've been working on chat functionality for my website hosted on Azure app service. I'm using the socket on port 443 as app service won't allow any other port than 80 and 443.
Socket functionality works fine on localhost but this error shows up when I deploy:
websocket.js:122 WebSocket connection to 'wss://mydomain/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 500
this is I'm connecting on client-side:
const socket = io.connect("https://mydomain:443", {transports: ['websocket'], secure: true, port: '443'});
This is my server.js file
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const base = require("./routes/api/base");
const leads = require("./routes/api/leads");
const requests = require("./routes/api/requests");
const offApp = require("./routes/api/offApp");
const chat = require("./routes/api/chat");
const chatSocket = require("./routes/socket/chat");
const path = require("path"); // on top
const app = express();
const cors = require('cors')
const https = require('https');
const fs = require('fs');
/**
* App.
*/
const privateKey = fs.readFileSync('private.key').toString();
const certificate = fs.readFileSync('certificate.crt').toString();
const ca = fs.readFileSync('ca_bundle.crt').toString();
const server = https.createServer({key:privateKey,cert:certificate,ca:ca }, app);
const client = require('socket.io').listen(server);
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
client.origins('*:*');
client.set('transports', ['websocket']);
server.listen(443);
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }, (err, db) => {
if (err) {
throw err;
}
console.log('MongoDB connected');
chatSocket(db, client);
});
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use("/api/base", base);
app.use("/api/leads", leads);
app.use("/api/requests", requests);
app.use("/api/offapp", offApp);
app.use("/api/chat", chat);
const port = process.env.PORT || 5000;
app.use(express.static("client/build")); // change this if your dir structure is different
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
app.listen(port, () => console.log(`Server up and running on port ${port} !`));
I haven't found any error in logs

I was able to solve this problem by using the default port. (Not the best solution but for Azure App service I couldn't find any other solution)
For the client-side I am connecting to socket like this.
const socket = io.connect("https://example.com", {transports: ['websocket'], secure: true});
And this is how my server-side looks like.
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const base = require("./routes/api/base");
const leads = require("./routes/api/leads");
const requests = require("./routes/api/requests");
const offApp = require("./routes/api/offApp");
const chat = require("./routes/api/chat");
const chatSocket = require("./routes/socket/chat");
const path = require("path"); // on top
const app = express();
const cors = require('cors')
const https = require('https');
const fs = require('fs');
/**
* App.
*/
var privateKey = fs.readFileSync('private.key').toString();
var certificate = fs.readFileSync('certificate.crt').toString();
var ca = fs.readFileSync('ca_bundle.crt').toString();
// var server = https.createServer({key:privateKey,cert:certificate,ca:ca }, app);
var server = require('http').createServer(app);
var client = require('socket.io').listen(server);
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
client.origins('*:*');
client.set('transports', ['websocket']);
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }, (err, db) => {
if (err) {
throw err;
}
console.log('MongoDB connected');
chatSocket(db, client);
});
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use("/api/base", base);
app.use("/api/leads", leads);
app.use("/api/requests", requests);
app.use("/api/offapp", offApp);
app.use("/api/chat", chat);
const port = process.env.PORT || 5000;
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
server.listen(port);

Related

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.

Socket.io + node JS = Error during handshake: error code 500

I was working on Socket.io and node jS to develop a chat web app. It worked locally but I have faced many issues when I deployed my changes to Azure app service.
I am creating a secure connection on port 443. I have resolved other issues but I can't resolve this one.
This the error I'm getting in console on client side.
WebSocket connection to 'wss://mydomain/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 500
This is how I'm connecting on server side
var socket = io.connect("https://mydomain:443", {transports: ['websocket'], secure: true, port: '443'});
and this is my server.js code:
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const base = require("./routes/api/base");
const leads = require("./routes/api/leads");
const requests = require("./routes/api/requests");
const offApp = require("./routes/api/offApp");
const chat = require("./routes/api/chat");
const chatSocket = require("./routes/socket/chat");
const path = require("path"); // on top
const app = express();
const cors = require('cors')
const https = require('https');
const fs = require('fs');
var options = {
pfx: fs.readFileSync('certificate.pfx'),
passphrase: 'password'
};
app.use(cors());
var server = https.createServer(options, app);
var client = require("socket.io").listen(server);
client.origins('*:*');
client.set('transports', ['websocket']);
server.listen(443);
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }, (err, db) => {
if (err) {
throw err;
}
console.log('MongoDB connected');
chatSocket(db, client);
});
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use("/api/base", base);
app.use("/api/leads", leads);
app.use("/api/requests", requests);
app.use("/api/offapp", offApp);
app.use("/api/chat", chat);
const port = process.env.PORT || 5000;
app.use(express.static("client/build")); // change this if your dir structure is different
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
app.listen(port, () => console.log(`Server up and running on port ${port} !`));
I have checked the logs, there are no errors there.

Socket.io and node JS resulting CORS blocked issue

I've been working on chat functionality. There are two kinds of clients, One is the frontend of my application and the second is random another website.
I know there are plenty of issues like this but I tried all of the solution but I'm still getting following error:
Access to XMLHttpRequest at 'https://mydomain/socket.io/?EIO=3&transport=polling&t=NCjoM1w' from origin 'null' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
and this the error I'm getting on client-side of my own front end:
https://mydomain/socket.io/?EIO=3&transport=polling&t=NCjnJUX 404 (Not Found)
This is how I'm trying to connect from client-side.
var socket = io.connect("https://mydomain:443/", {secure: true, port: '443'});
and this is my server.js code
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const base = require("./routes/api/base");
const leads = require("./routes/api/leads");
const requests = require("./routes/api/requests");
const offApp = require("./routes/api/offApp");
const chat = require("./routes/api/chat");
const chatSocket = require("./routes/socket/chat");
const path = require("path"); // on top
const app = express();
// const client = require('socket.io').listen(4000).sockets;
const https = require('https');
const fs = require('fs');
var options = {
pfx: fs.readFileSync('certificate.pfx'),
passphrase: 'password'
};
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, *');
next();
});
var server = https.createServer(options, app);
var client = require("socket.io").listen(server);
client.origins('*:*') ;
server.listen(443);
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }, (err, db) => {
if (err) {
throw err;
}
console.log('MongoDB connected');
chatSocket(db, client);
});
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use("/api/base", base);
app.use("/api/leads", leads);
app.use("/api/requests", requests);
app.use("/api/offapp", offApp);
app.use("/api/chat", chat);
const port = process.env.PORT || 5000;
app.use(express.static("client/build")); // change this if your dir structure is different
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
app.listen(port, () => console.log(`Server up and running on port ${port} !`));
Please help me resolve this CORS and other issues. I am using the Azure app service. That's why I can't use any other port than 80 and 433
Install cors package using npm i cors
In your app.js file,
const cors = require('cors')
app.use(cors());
// use CORS like that-
// you need to use it as middle ware
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Danish try this solution, I hope it will work
const client = require("socket.io")(server, {
handlePreflightRequest: (req, res) => {
const headers = {
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Allow-Origin": req.headers.origin, //or the specific origin you want to give access to,
"Access-Control-Allow-Credentials": true
};
res.writeHead(200, headers);
res.end();
}
});
client.on("connection", () => {
console.log("Connected!");
});
server.listen(443);

my app have a problem after i refresh the page

when i open my app for the first time it work just fine but when i refresh the page it give me a url to my index.html file ( /client/build/index.html ) , i have deploy it on heroku
that is the code in my app.js file that create the server
const express = require('express');
const app = express();
const path = require('path');
// create a server for socket io
const http = require('http');
const socketio = require('socket.io');
const server = http.createServer(app);
module.exports = io = socketio(server);
// my middle ware
const morgan = require('morgan');
const bodyParser = require('body-parser');
// Init Middelware
app.use(express.json({ extended: false }));
// my router
const postRoute = require('./nodeapi/routers/post');
const authRouter = require('./nodeapi/routers/auth');
const usersRouter = require('./nodeapi/routers/users');
const friendRouter = require('./nodeapi/routers/friend');
const chatRouter = require('./nodeapi/routers/chats');
const mongoDB = require('./nodeapi/mongodb-database/db');
const port = process.env.PORT;
// Connect monogo database
mongoDB();
// Middel ware
app.use(morgan('dev'));
app.use(bodyParser.json());
// Get the routes
app.use('/', postRoute);
app.use('/', authRouter);
app.use('/', usersRouter);
app.use('/', friendRouter);
app.use('/', chatRouter);
app.use('/file/', express.static('./uploads/'));
// connect to socket io
io.on('connection', (socket) => {});
//Serve static assets in productio
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('./client/build'));
app.get('*', (req, res) => {
res.send(path.resolve(__dirname, '..', 'client', 'build', 'index.html'));
});
}
// listen to the port
server.listen(port, () => {
console.log(`this is port ${port}`);
});
this is when i open it for the first time
this is when i refresh the page
You just need to send it as file not a text
app.use(express.static('./client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'client', 'build', 'index.html'));
});

Cannot start NodeJS Server with Socket.io

So, I have the simple dream to start the Server with Socket.io library, but for some reasons it's does not happen... I cannot understand what is wrong, because I do not gets even the standart message on server run - Server running on port ${port}.
Help, please...
'use strict'
const express = require('express');
const http = require('http');
const io = require('socket.io');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const bcrypt = require('bcrypt-nodejs');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const app = express();
const server = http.Server(app);
const socketServer = io(server);
const router = express.Router();
const chat = require('./routes/chat');
const profile = require('./routes/profile');
const registration = require('./routes/registration');
const login = require('./routes/login');
const logout = require('./routes/logout');
const EmployersSchemaDB = require('./SchemaDB/EmployersSchemaDB');
const MessagesSchemaDB = require('./SchemaDB/MessagesSchemaDB');
const User = require('./SchemaDB/ShemaAuthtificaion');
mongoose.connect('mongodb://test_db');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers');
res.setHeader('Cache-Control', 'no-cache');
next();
});
app.use(session({
secret: 'work hard',
resave: true,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
router.route('/')
.get((req, res) => {
res.json('Hello on the Homepage!');
});
app.use('/', router);
app.use('/chat', chat);
app.use('/profile', profile);
app.use('/auth/login', login);
app.use('/auth/logout', logout);
app.use('/auth/registration', registration);
const port = process.env.API_PORT || 8989;
socketServer.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Change from this:
socketServer.listen(port, () => {
console.log(`Server running on port ${port}`);
});
to this:
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
You need to start your http server. That's the core server here that works with both Express and socket.io and fields all incoming requests.
Your variable socketServer and your io variable are misnamed (which is probably part of your confusion). socketServer is the actual server, that's the socket.io server-side instance which is typically named io. See the socket.io server doc for details.
You should start with a simpler server:
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const app = express();
const server = http.createServer(app);
const socket = socketio(server);
app.use(express.static(`./public`));
socket.on('connect', socket => {
socket.emit('identify', {'server':'server data'});
});
socket.on('data', data => {
console.log(data);
});
server.listen(4000, () => {
console.log('Server up and running on port 4000');
});
In the front end you can test this like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>test
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
<script type="text/javascript">
'use strict';
var socket = io('http://localhost:4000');
socket.on('identify', function (socket) {
console.log(socket);
});
</script>
</body>
</html>

Resources