I am trying to connect my quasar application to a socket.io express server hosted on heroku.
The problem is that every time I try to connect, the browser says the request is pending and on the backend I never receive the message of connection.
This is my backend code
const express = require('express');
const app = express();
const PORT = process.env.PORTA || 3000;
const server = app
.use((req, res) => {})
.listen(PORT, () => console.log(`Server is running on port ${PORT}...`));
const io = require('socket.io')(server, {
cors: {
origin: '*',
credentials: true
}
});
io.on('connection', socket => {
console.log('Connected: ' + socket.id);
});
And this is the connection in a boot file in quasar (vue.js) with socket.io extended
import Vue from 'vue'
import VueSocketIOExt from 'vue-socket.io-extended';
import { io } from 'socket.io-client';
const socket = io(URL_CONNECTION);
Vue.use(VueSocketIOExt, socket);
As you can see on the backend I have a console.log to see the id of the connected client. If I try this locally in my pc it works fine and I get the socket id, but on heroku the client doesn't connect without giving me any error.
I found a way to do this. I just removed the custom port I inserted in the server and I put the default (process.env.PORT) and then I connected from the client giving the port 80.
Now, I don't know why, but it's working.
Related
I have the following (simple) websocket code using socket.io in a node.js-project:
// index.js
const express = require("express");
const app = express();
const http = require("http");
const socketIo = require("socket.io");
const server = http.createServer(app);
const io = socketIo(server);
io.on("connection", (socket) => {
console.log("New client connected");
socket.on("disconnect", () => {
console.log("Client disconnected");
});
});
server.listen(4000, () => console.log('Server running...'));
I'm using a chrome extension to test if I can connect to this server. I'm using Simple Websocket Client.
When I enter the following URL's, I cannot connect to the server:
ws://localhost:4000
ws://127.0.0.1:4000
ws://testserver.loca.lt (localtunnel)
I get an "undefined" error, so it seems there is no error data.
I'm using chrome on macOS. Previously (a few months ago) I was able to create socket.io-servers and connect to them on this machine.
EDIT:
This is the error in the developer console:
websocket.js:88 WebSocket connection to 'ws://localhost:4000/socket.io/?EIO=4&transport=websocket' failed:
There is no error code or error behind 'failed'.
I'm trying to make a real-time socket.io app in Angular and Node, exactly like what is explained here. I set up the server and the client connection, but the connection is never made.
Server Code:
const port = process.env.PORT || 8080;
const host = process.env.BASE_URL || 'http://127.0.0.1';
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('a user connected');
socket.broadcast.emit('message-broadcast','Started');
socket.on('message', (msg) => {
console.log(msg);
socket.broadcast.emit('message-broadcast',msg);
})
});
server.listen(port, () => console.log(`listening on port ${port} + host ${host}`));
I had some issues with setting up the client code as it's explained in the tutorial. When I used the line
import * as io from 'socket.io-client';
and then tried to call
this.socket = io(environment.SocketEndpoint);
I received an error "This expression is not callable."
After some fiddling around I replaced the import line with
import { io } from 'socket.io-client';
import { Socket } from 'socket.io-client';
and the connect function with
setupSocketConnection(){
this.socket = io(environment.SocketEndpoint).connect();
this.socket.on('message-broadcast', (data: string)=>{
console.log('Recieved message:',data);
})
console.log('Set up socket',this.socket);
}
This MIGHT be related to the issue, but I don't think it is.
When I do this, it APPEARS to work, in the sense that I can see periodic calls in the Networking tab, which look like
http://localhost:8080/socket.io/?EIO=4&transport=polling&t=NbRCamo
But none of these calls do anything. They show up red in the Networking tab. The timing tab says they are "stalled". On the server, there is no console log associated with these calls, nor does the client receive any kind of emitted message.
What's odd is that I CAN get a response by pasting this call in the browser, which looks like this:
0{"sid":"3KsDDAa1mA2OVxKIAADT","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000}
But there is still no console logging on the server. In fact any call that starts with "server.io" doesn't create any logging at all. But if I make any other call to the server that doesn't start with "socket.io", I DO get a console log recording that the call was made - even if it's only a 404 error. So I know that socket.io must be doing SOMETHING, it just isn't doing what it's supposed to.
EDIT: Okay, when I uploaded it to a different server it seems to work all right - it's only a problem with localhost, apparently. I guess I could manage, but being able to test on localhost would be convenient, so if anyone can figure this out it would be helpful.
EDIT2: It was caused by a CORS policy issue. I was able to fix it by changing the server code to this:
const port = process.env.PORT || 8080;
const host = process.env.BASE_URL || 'http://127.0.0.1';
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server, {
cors: {
origin: "http://localhost:4200",
methods: ["GET", "POST"]
}
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.broadcast.emit('message-broadcast','Started');
socket.on('message', (msg) => {
console.log(msg);
socket.broadcast.emit('message-broadcast',msg);
})
});
server.listen(port, () => console.log(`listening on port ${port} + host ${host}`));
This might be related to CORS problems. I had a similar issue where i had the socketio server running on port 5000, the angular app on 4200, which the CORS policy did not like at all. I solved this using a proxy configuration and starting the dev server with --proxy-config proxy.json.
proxy.json:
{
"/socket.io": {
"target": "http://localhost:8080",
"secure": false,
"ws": true,
"changeOrigin": true,
"logLevel": "debug",
"pathRewrite": { }
}
}
Not sure if it's the same issue for you though.
Premising I'm new to sockets, I'm trying to set up the first configuration on server (Node w/Express).
While doing so, I encountered an issue where nodemon crashes every time I save, by returning Error: listen EADDRINUSE: address already in use :::8080.
Here the server implementation:
import express from "express";
import cors from "cors";
import { Server, Socket } from "socket.io";
import { createServer } from "http";
import morgan from "morgan";
// App configuration
const app = express();
const server = createServer(app);
const io = new Server(server);
const port = process.env.PORT || 8080;
// Middlewares
app.use(cors());
app.use(express.json());
app.use(morgan("combined"));
// Socket connection
io.on("connect", (socket: Socket) => {
socket.send("test");
});
server.listen(port, () => {
console.log(`Server is up and running on ${process.env.NODE_ENV} - port ${port}`);
});
I would think that happens as the socket.io connection never get closed / disconnected, leaving the server instance up listening.
I had a look around and found many q/a that were suggesting commands to find and kill the process, but I'd need a solution able to disconnect the socket automatically every time the express server gets turned down.
I tried the following:
io.on("disconnect", () => {
io.sockets.disconnect();
}
As suggested here, but TS complains about io.sockets.disconnect() with a Property 'disconnect' does not exist on type 'Namespace<DefaultEventsMap, DefaultEventsMap>'.ts(2339).
Any idea how this should be tackled?
I think there may be an issue in socket io initialization. Can you try this type of initialization showed at https://socket.io/get-started/chat#Integrating-Socket-IO:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
So basically pass server object to the default import from socket io like this(right now, you are using "Server" inside socket.io ):
import express from "express";
import cors from "cors";
import ioDefault, { Server, Socket } from "socket.io";
import { createServer } from "http";
import morgan from "morgan";
// App configuration
const app = express();
const server = createServer(app);
const io = ioDefault(server);
const port = process.env.PORT || 8080;
// Middlewares
app.use(cors());
app.use(express.json());
app.use(morgan("combined"));
// ...
UPDATE:
The issue was another server running on the same port. To check which process is running on a specific port you can run
netstat -anpe | grep "8080" | grep "LISTEN"
if netstat is not installed run sudo apt install net-tools in debian based systems(ubuntu, fedora and others)
you can then kill it with its pid:
kill -9 5454
I want to use Socket.io with a React frontend and NodeJS & Express backend but have both running on different ports for development (Fontend: 3000; Backend: 8080).
When the Socket.io-Client has loaded my frontend executes var socket = io('http://localhost:8080'); and then automatically makes a GET request to http://localhost:8080/socket.io/?EIO=4&transport=polling&t=NSlH7of. That request should normally return something like 0{"sid":"XXX","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000} but the Chrome Dev Tools say that the status is (failed) net::ERR_FAILED. There also is no response available in the Dev Tools.
However when I run the GET request in my HTTP-Client it returns exactly what I expect it to return.
That error looks like it's caused by the Socket.io-Client but I get no error whatsover besides the failed GET request. When I run everything on one port (Frontend served with webpack by the backend) the request goes through as expected.
I would appreciate any help! Thanks!
server.js
const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
//Serve static react app
app.use(express.static('dist'));
app.use('/app', express.static('dist'));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '../../../' + '/dist/index.html'));
});
io.on('connection', (socket) => {
console.log('Connected')
socket.on('join-game', (gameId, userId) => {
console.log(gameId, userId);
})
})
http.listen(process.env.PORT || 8080, () => {
console.log(`Listening on port ${process.env.PORT || 8080}!`);
});
I finally resolved the error!
The problem was that the request was blocked by CORS of Chrome.
I changed the line const io = require('socket.io')(http) to const io = require('socket.io')(http, { cors: {}});.
Now everything is working as it should.
If you want to hit port 8080 for your socket.io connection, you must set up a server for that port in your nodejs program (your back end). Code running in browsers (front-end code in React parlance) like your code
var socket = io('http://localhost:8080')
can only originate connection requests. And, if no server is listening for those requests, you get the failure status that your devtools showed you.
By the way, you'll be wise to make your nodejs server program use just one port. With just one port, it's much simpler to deploy to a production server.
I have been fighting with setting this up for longer than I would like to admit.
At first, I was having CORS issues, after following what the socket.io documentation / other stack overflow threads I was getting hit with, GET / POST 400 errors.
Finally after that, I noticed a few threads mention to pass in {transports: ['websocket']} on the server and in the client.
Once I did that, I stopped getting error messages, however, I am still not able to make a connection from my client to my socket.io server. I am hoping I can get some guidance.
I am running Socket.io 3.0 and express 4+
Here is what my server / client looks like at the moment..
SERVER (As an express router)
const express = require('express');
const socketIO = require("socket.io");
const http = require('http');
let app = express();
let router = express.Router();
let server = http.createServer(app);
// The event will be called when a client is connected.
let io = socketIO(server, {transports: ['websocket']})
io.on("connection", socket => {
console.log("connection")
socket.emit("hello", { data: "more data" })
socket.on("disconnect", () => {
console.log("user left")
})
})
server.listen(8081, () => console.log('Socket.io listening on *:8081'));
module.exports = router;
Client (React)
// Socket.IO
import io from 'socket.io-client';
const socket_io = io('localhost:8081', {transports: ['websocket']})
// Socket.io UseEffect
useEffect( () => {
const initSocket = () => {
console.log(socket_io)
socket_io.on("hello", data => {
setSocket(data);
console.log(data);
});
// CLEAN UP THE EFFECT
return () => socket_io.disconnect();
}
initSocket()
},[])
Here is what my Console currently looks like when I log out the socket connection:
So, as embarrassing as this is, the breaking change was that the socket.io-client module in the React client application wasn't 3.0 like the one on the server. Therefore they weren't able to handshake.
My advice, is if you have the CORS rule added or the transport: websocket added, make sure you look at your package.json file in your server / client apps to make sure that the socket.io package version matches.