nodejs + express + socket.io > socket client connection issue on remote server - javascript

Im trying to make a little chat, using NodeJS, Express ans socket.io
For debugging Im using localhost, log4js, and locally it is working fine, socket.io is working with no problem.
But when I try to deploy it on remote server, it isnt working.
Here is a link https://cryptic-fjord-64553.herokuapp.com/
Ofc, I googled, wrote similar topics, tried a lot of stuff, but it isnt working.
Failed to load resource: the server responded with a status of 404
engine.io-client:socket socket error {"type":"TransportError","description":404}
or
engine.io-client:socket socket error {"type":"TransportError","description":0}
My server, app.js includes this:
var express = require('express'),
app = express(),
logger = require('log4js').getLogger();
server = require('http').Server(app),
io = require('socket.io')(server),
this commented block instead server=.. and io=.. above when Im trying to deploy my app on the remote server (heroku)
/*
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Headers", "Content-Type");
res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
next();
});
var https = require('https'),
socketio = require('socket.io'),
server = https.createServer(app),
io = socketio.listen(server, {log:false, origins:'*:*'});
app.set('port', (process.env.PORT || 5000));
*/
When I try to deploy app on heroku, I comment server.listen.. block below
var pug = require('pug'),
port = 4000;
server.listen(port, '127.0.0.1', ()=>{
var addr = server.address();
logger.level = 'debug';
logger.debug('listening on ' + addr.address + ':' + addr.port);
});
app.use(express.static(__dirname + '/public'));
app.get('/socket.io.js', (req,res)=>{
res.sendFile(__dirname + '/node_modules/socket.io-client/dist/socket.io.js');
});
app.get('/socket.io/socket.io.js', (req,res)=>{
res.sendFile(__dirname + '/node_modules/socket.io-client/dist/socket.io.js');
});
app.get('/jquery.js', (req,res)=>{
res.sendFile(__dirname + '/node_modules/jquery/dist/jquery.min.js');
});
app.set('views', __dirname + '/views');
app.set('view engine', 'pug');
const amazingStuff = 'Its amazing stuff, ',
date = new Date;
app.get('/', (req,res)=>{
res.render('pages/index', {
title: 'main page',
message: date,
showChat: false
});
io.on('connection', (socket)=>{
socket.on('newUserJoin', (userName)=>{
socket.session = {};
socket.session.userName = userName;
socket.session.address = socket.handshake.address;
socket.session.id = socket.id;
socket.broadcast.emit('newUser', socket.session);
socket.emit('user', socket.session)
socket.emit('userLisr', io.length)
logger.info('user ' + socket.session.userName + ' / ip ' + socket.session.address)
logger.info('user count: ' + io.engine.clientsCount)
logger.debug(socket.session)
var clients = io.sockets.connected,
clientList = {};
for (var i in clients){
if(clients[i].session) clientList[i] = clients[i].session;
}
socket.emit('clientList', clientList);
})
//get a new message and share it to all users
socket.on('newMessage', (message)=>{
socket.broadcast.emit('shareMessage', message)
})
})
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
versions:
"devDependencies": {
"nodemon": "^1.11.0"
},
"dependencies": {
"express": "^4.15.3",
"jquery": "^3.2.1",
"log4js": "^2.3.3",
"pug": "^2.0.0-rc.3",
"socket.io": "^2.0.3"
}
client, main.js:
var socket = io();
//var socket = io.connect('https://cryptic-fjord-64553.herokuapp.com/');
and handlers
and here is adding scripts in html(pug), first works locally, commented stuff are attempts I tried to do for deploying on heroku, but it doesnt work.
script(src='/socket.io/socket.io.js')
//-script(src='/socket.io.js')
//-script(src='https://cryptic-fjord-64553.herokuapp.com/socket.io.js')
U cant open the link above and take a look whats going on in the console. There are no warnings regarding client side script, I mean main.js file, so it can connect to the server and main.js knows what is 'io'. So it seems like its ok with links in the html and socket.io connection to the server. So probably its problem in the server side app.js
How can I force it to work on heroku?

Related

How can I connect 2 node.js app eachother ?(one of client app -one of server app) + socket.io

I'm new to node.js and socket.io. They asked me to divide the connect4 game (I made with Javascript,node.js, express, socket.io, jquery ) into 2 separate apps (server app and client app).
The node.js of these two Apps must be connected to each other. In other words, I need to connect Client App's Node application to the port of the Server App's node application. (They said I should have 2 working ports belonging to 2 applications)
(Before divided the app it was working normal; when client give the url of the room he can play with his friend, game start and over normally But now everything mixed.)
Connect 4 game was working when client and server in the same App but now I cant do something like that
"
app.get('/:room([A-Za-z0-9]{9})', function(req, res) //app.set('view engine', 'html'); //res.status(200).sendFile(__dirname+'./index.html');
"
But my main problem is I couldn't connect from Client App nodejs to Server app nodejs .
Code part of the server app;
const express = require('express');
const cors = require('cors');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http ,{
cors: {
origin: '*',
methods: ['GET', 'POST'],
},
serveClient: false,
pingInterval: 5000,
});
const port = process.env.PORT || 4000;
const { randomNumeric } = require('./utils.js');//I want random room key for later
// TODO: IF CORS DOES NOT WORK, TRY TO USE IT IN EXPRESS SERVER
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
res.header('Access-Control-Allow-HEADERS', 'Content-Type');
});
io.listen(port, () => { //Its not working :(
console.log("çalışıyor");
console.log(`Server started at ${port}`);
});
And Client App node.js code;
var express = require('express'),
game_logic = require('./game_logic'),
app = express(),
server = require('http').createServer(app),
port = Number(process.env.PORT || 3000);
server.listen(port);
console.log('Node.js web server port 3000 de çalıştı')
/*routing*/
app.use("/css", express.static(__dirname + '/css'));
app.use("/js", express.static(__dirname + '/js'));
app.use("/img", express.static(__dirname + '/img'));
app.get('/', function(req, res) {
res.sendFile(__dirname+'/index.html');
});
And in Client App I have App.js for socket.io connect
$(function(){
var socket = io.connect(),
player = {},
yc = $('.your_color'),
oc = $('.opponent_color'),
your_turn = false,
url = window.location.href.split('/'),
room = url[url.length-1];
after that I have code for connect socket.io like socket.on and socket.emit
when I run this 2 App and open the local3000 I just saw empty game board nothing happened,
Can you help me about this and I really need to some links about this topic. Thank u

Socket IO and Express Cross origin error or 404 not found error in console

I am getting cross origin headers error despite running cors library, or simply a 404 not found while polling in the console.
The project structure looks like this
My goal is to have the little chat widget on every view. I will include this to the other views as EJS partial.
I am not sure what I going wrong I have tried to run Express on port 5000 and Socket IO on 8080 or 3000, all different combinations have not yielded anything good.
APP.JS looks like this
const { check } = require('express-validator');
const express = require("express");
const session = require("express-session");
const MongoDBStore = require("connect-mongodb-session")(session);
const config = require("config");
const flash = require('express-flash');
const cookieParser = require('cookie-parser');
const nodemailer = require("nodemailer");
const Mailgen = require("mailgen");
const dotenv = require('dotenv');
dotenv.config();
const appController = require("./controllers/appController");
const isAuth = require("./middleware/is-auth");
const connectDB = require("./config/db");
const mongoURI = config.get("mongoURI");
const bodyParser = require('body-parser');
var cors = require('cors') // This should help, but does nothing
const app = express();
const http = require('http').Server(app); // I suspect the mistake is in these lines
const io = require('socket.io')(http,
{
cors: {
origin: "http://localhost:5000", // Does nothing
credentials: true
}})
connectDB();
const store = new MongoDBStore({
uri: mongoURI,
collection: "mySessions",
});
app.use(cors({origin: '*'})) // Also seems not to be working
app.set("view engine", "ejs");
app.use(express.urlencoded({ extended: true }));
//Middleware and Routes
io.sockets.on('connection', function(socket) {
console.log("hello") // never happened
socket.on('username', function(username) {
console.log("hello") // never happened
socket.username = username;
io.emit('is_online', '🔵 <i>' + socket.username + ' join the chat..</i>');
});
socket.on('disconnect', function(username) {
io.emit('is_online', '🔴 <i>' + socket.username + ' left the chat..</i>');
})
socket.on('chat_message', function(message) {
io.emit('chat_message', '<strong>' + socket.username + '</strong>: ' + message);
});
});
app.listen(5000, console.log("App Running on http://localhost:5000"));
And the front end partial EJS looks like this
<ul id="messages"></ul>
<form action="/" method="POST" id="chatForm">
<input id="txt" autocomplete="off" autofocus="on" oninput="isTyping()" placeholder="type your message
here..." /><button>Send</button>
</form>
The rest of the front end page looks like this
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style> etcetc
<%- include ('./partialChatWidget.ejs') %>
And the JS
<Script>
var socket = io.connect('http://localhost:5000', { transport : ['websocket'] } );
$('form').submit(function(e){
e.preventDefault();
socket.emit('chat_message', $('#txt').val());
$('#txt').val('');
return false;
});
socket.on('chat_message', function(msg){
$('#messages').append($('<li>').html(msg));
});
socket.on('is_online', function(username) {
$('#messages').append($('<li>').html(username));
});
var username = prompt('Please tell me your name');
socket.emit('username', username);
</script>
So what is going wrong here, do I need 2 servers on different ports or 2 instances, I always thought socket IO borrows the http server , not the express instance.
Thanks for helping me out. I might add I get the cross origin errors when I try to run on 2 different ports. Else I get 404 not found in the console. The page and the partial and the initial JS(Jquery) run.
After a lot of back and forth....
Just make sure to load the front end link for socket IO right in the head section asap.
And do include this part on the front end
var socket = io.connect('http://localhost:5000', { transport : ['websocket'] } );
Definitely include this on the server side, this cant hurt, unless you want to block some pages from CORS access
app.use(cors({origin: '*'}))
The next 2 steps made it all work.
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http,
{
cors: {
origin: "http://localhost:5000 {this is the port of your back end app, not for the socket IO port }",
credentials: true
}})
And finally, indeed, 2 servers.
const server = http.listen(8080, function() {
console.log('listening on *:8080');
});
app.listen(5000, console.log("App Running on http://localhost:5000"));
Took me a while, but now everything is clear once and for all(I hope)
app.use((req,res, next)=>{
res.setHeader('Access-Control-Allow-Origin',"http://localhost:3000");
res.setHeader('Access-Control-Allow-Headers',"*");
res.header('Access-Control-Allow-Credentials', true);
next();
});
use this code
and install the older socket.io version 2.3.0
try this code
`const server = app.listen(PORT,()=>console.log(`listening on port ${PORT}`));
io = require('socket.io').listen(server);
io.on('connection', (socket) => {
console.log('a user connected');
});`

Socket.io.js is not loaded

I'm working with node.js and express.js, and I'm trying to add socket.io to one of my .ejs files but when I'm doing that I get some weird errors:
Failed to load resource: the server responded with a status of 404 (Not Found) socket.io/?EIO=3&transport=polling&t=MV6f2K2
Failed to load resource: the server responded with a status of 404 (Not Found) socket.io/?EIO=3&transport=polling&t=MV6f2cR
and then,per second :
GET https://www.mywebsite.eu/socket.io/?EIO=3&transport=polling&t=MV6f2cR 404 (Not Found) socket.io.js:7
There are my files:
app.js:
const fs = require('fs');
const express = require('express');
const app = express();
const http = require('http').Server(app);
const fileUpload = require('express-fileupload');
var io = require('socket.io')(http);
.....
var router = express.Router();
var pathView = __dirname + "/views/";
app.use(express.urlencoded({extended: true}));
app.use(express.json());
const listenPort = 8000;
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use('/public', express.static('public'));
app.use('/scripts', express.static(__dirname + '/node_modules/'));
//SOCKET IO PART
io.on('connection', function(socket){
console.log('a user connected');
});
//SOCKET IO PART
..........
app.get & app.post requests
..........
app.use( "/", router);
// Not found
app.use("*",function(req,res){
res.setHeader('Content-Type', 'text/html');
res.status(404).send('Page introuvable !');
});
// Run server
app.listen(listenPort, function () {
console.log('Example app listening on port ' + listenPort )
})
profile.ejs:
.....content of the page(it's working well).......
<%- include('scripts') -%>
<script src="/scripts/socket.io/socket.io.js"></script>
</html>
<script>
var socket = io();
</script>
I have to mention that I copied the socket.io.js from socket.io-client and I put it into socket.io if I wouldn't have done that I would have got a 404 file missing error in devtools.
Hope the rest of the code is not required, I didn't add it because it was a lot and it has nothing to do with socket.io.
I think you should try and break it down a little bit to identify your problem. You are clearly not reaching your socket.
Try to have a server just like this:
var express = require('express')
var app = express()
var server = require('http').Server(app)
var io = require('socket.io')(server)
io.on('connection', function(socket) {
console.log('Socket did connect');
});
server.listen(8080)
And Client:
var socket = io();
If this works, which it very much should, try to add the rest of your code. Ejs shouldn't be the problem since it's compiled to regular HTML before it's served.
A problem would be if you have you client running on a different domain (or port) than the server. If so, you would have to define it inside the io() on the client site, eg: var socket = io("http://localhost:8080")

How to get my simple Node.js socket application working in Elastic Beanstalk

My experience with sockets have generally been to run a server in a terminal, set up a client in another terminal, and watch them interact with each other.
I found a very basic Node.js socket application tutorial as pictured. The client auto generates numbers, and sends them to the client to echo back.
It is my first time using Elastic Beanstalk. I managed to get past all of the other issues I was having, and now it is launching the url.
My server.js/client.js/app.js isn't printing to the Console using the developer tools (F12), and I am wondering why (you can see in my code I have put very blatant console logs). Sources also only shows the index.jade file (not server.js, client.js etc)
I am also relatively new to Node.js.
What I want to do is simulate/run my client so it will interact with the server that is now on Beanstalk. I want the client to generate its numbers, and for the server to print it to the console (in the browser).
It works fine locally. I hope I have made my issue clear.
I thought maybe it is because I am not forcing client to launch somewhere in my code. However, as you can see in package.json, I am telling server.js to start (and server.js won't print to console in the browser, even though there are plenty of console.logs in there).
app.js
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 index = require('./routes/index');
var users = require('./routes/users');
console.log("HI IM IN APP.JS");
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(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);
// 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');
});
app.set('port', process.env.PORT || 8081);
app.listen(8081);
module.exports = app;
client.js
#!/usr/bin/env node
var WebSocketClient = require('websocket').client;
var client = new WebSocketClient();
console.log("HELLO I AM YOUR CLIENT :D");
client.on('connectFailed', function(error) {
console.log('Connect Error: ' + error.toString());
});
client.on('connect', function(connection) {
console.log('WebSocket Client Connected');
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
function sendNumber() {
if (connection.connected) {
var number = Math.round(Math.random() * 0xFFFFFF);
connection.sendUTF(number.toString());
setTimeout(sendNumber, 1000);
}
}
sendNumber();
});
client.connect('ws://localhost:8081/', 'echo-protocol');
server.js
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8081, function() {
console.log((new Date()) + ' Server is listening on port 8081');
});
console.log("HELLO I AM HERE. I'M YOUR SERVER :D");
wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
package.json
{
"name": "nodewebsockets",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node server.js"
},
"dependencies": {
"body-parser": "~1.18.2",
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.15.5",
"jade": "~1.11.0",
"morgan": "~1.9.0",
"serve-favicon": "~2.4.5"
}
}

ExpressJs is not serving index.html

I have an Angular client application that runs entirely in the browser. I am trying to use expressjs to host it. I modeled the server code after the server.js in John Papa's MEAN Hot Towel application that he uses in his Pluralsight Gulp course. This is my server code:
var express = require('express');
var app = express();
var port = process.env.PORT || 7203;
var environment = process.env.NODE_ENV;
console.log('About to crank up node');
console.log('PORT=' + port);
console.log('NODE_ENV=' + environment);
app.get('/ping', function(req, res) {
console.log(req.body);
res.send('pong');
});
console.log('** DEV **');
app.use(express.static('./src/app'));
app.use(express.static('./'));
app.use(express.static('./temp'));
app.use('/*', express.static('./src/index.html'));
app.listen(port, function() {
console.log('Express server listening on port ' + port);
console.log('env = ' + app.get('env') +
'\n__dirname = ' + __dirname +
'\nprocess.cwd = ' + process.cwd());
});
When I navigate to localhost:port/ping, I get pong back. When I navigate to localhost:port/ I get a 404 error. Can someone tell me what I am doing wrong here?
As #tommyd456 stated in the comments above, you need to declare a route for '/', like so:
app.get('/', function(req, res) {
res.send('Hello!');
});
From the express documentation, it seems that express.static targets a folder.
So, replacing app.use('/*', express.static('./src/index.html')); by app.use('/*', express.static('./src')); fix your problem and index.html will be served under 'localhost:port/'
So after many hours of fiddling and reading I replaced this code:
app.use(express.static('./src/app'));
app.use(express.static('./'));
app.use(express.static('./temp'));
app.use('/*', express.static('./src/index.html'));
with this:
app.use(express.static(__dirname));
app.use(express.static(process.cwd()));
app.route('/*')
.get(function(req, res) {
res.sendFile(__dirname + '/index.html');
});
and it appears to have solved the problem

Categories