Socket.IO 404 works locally but not when deployed via Netlify - javascript

Socket.IO works locally but not when deployed via Netlify
Please excuse my code, i'm a newbie to node.js etc.
This is the error I get:
Failed to load resource: the server responded with a status of 404 () (socket.io, line 0)
Client:
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.dev.js"></script>
function syncObj() {
var socket = io.connect()
socket.emit('sync', `${objId}`)}
// Listen for events
function syncComplete() {
var socket = io.connect()
socket.on('sync', function (data) {
objId = data
noti5()
document.getElementById("note4").style.display = "none";
document.getElementById("note6").style.display = "none";
// What do do when sync is complete
// Say Something
// Refresh Screen
})
}
//Server:
const express = require('express');
const opn = require('opn');
const app = express();
const port = 5000
var socket = require('socket.io')
const cors = require("cors")
function allowCrossDomain(req, res, next) {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next()}
app.use(allowCrossDomain)
app.use(cors())
app.use('/', express.static(__dirname + '/public'))
var server = app.listen(port, function () {
console.log('listening to request on port 5000');
opn(`http://localhost:${port}`);
});
// Socket Setup
var io = socket(server);
io.on('connection', function (socket) {
console.log('made socket connection', socket.id)
socket.on("sync", function(data){
io.sockets.emit('sync', data)
})
})
Worked perfectly locally. Please help.

You should mention your url in the io.connect(url here)
try this:
var socket = io('/');
If we put '/' instead of url it will automatically take the url if it is localhost or hosted on other ip.You can also mention your full url here like this.
var socket = io('http://localhost:port')
//or something else
Here is an example:
server:
const express = require('express');
const app = express();
const socket = require('socket.io');
const port = process.env.PORT || 8080;
//starting the server
const server = app.listen(port,() => {console.log("server running")});
//connecting socket to the server
const io = socket(server);
io.set('transports', ['websocket']);
io.on('connection',socket =>{
// your code here
}
client:
var socket = io('/',{transports: ['websocket'],upgrade:false});
//on connection
socket.on('connect',data =>{
//logic here
}

Related

Problems with Webhooks and Websockets on the same port

I have a server that receives webhooks, sends them to a client via websockets. Since I am listening for both on the same port, if webhooks work, websockets dont and vice versa. How would I go about solving this. Here is the code for the server
const express = require('express');
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.json())
app.post("/", (req, res) => {
console.log(req.body);
res.status(200);
res.send(req.body);
echo(req.body);
});
app.listen(3000, '0.0.0.0', () => console.log('Server is live at 3000'));
const WebSocket = require('ws');
const SocketServer = require('ws').Server;
const server = express().listen(3000);
const wss = new SocketServer({server});
wss.on('connection', (ws) =>{
console.log("Connected");
ws.send("Connected To Server")
ws.on('close', () => console.log("Disconnected"));
});
function echo(webhook){
wss.clients.forEach(function each(client){
client.send(webhook);
});
}
How would I run webhook listener and websocket sender/listener on same port
Can I run both of them on different ports on the same url
a) If yes what would be the url for both ports, if my website is www.example.com
If all that is not possible, what would be a good alternative

Why can't I access my API on another computer?

I can't access my API/nodejs server [http://10.0.0.14:3000/] on another computer. If I search for [http://10.0.0.14:3000/] in the browser on my local computer the api is running on I get 'test' with statusCode 200 back. But if I try the same on another computer in the same network I get a timeout. Why does this happen?
const express = require('express');
const bodyParser = require('body-parser');
const { parse } = require('querystring');
const HOST = '10.0.0.14';
const PORT = 3000;
var app = express();
app.use(bodyParser.urlencoded({
extended: true
}));
app.listen(PORT, HOST,function() {
console.log("Server is listening on port 3000...");
});
app.use(bodyParser.json());
app.get('/', function(req,res) {
res.header("Access-Control-Allow-Origin", "*");
// let body = req.body;
console.log("GET ", req.body);
res.send("test");
});
if it is windows add a rule to the firewall for incoming data for port 3000

io.sockets.on not working inside a route in Node.js

I'm trying to use io.sockets.on inside a route in a Node.js and Express app. I have been following what is said here: https://stackoverflow.com/a/31277123/8271839
I can successfully send io.sockets.emit events, but I cannot receive events with io.sockets.on.
Here is my code:
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest');
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
app.set('socketio', io);
server.listen(4002);
io.sockets.on("connection",function(socket){
console.log("connected");
socket.on("connected", function (data) {
console.log("hello");
})
});
routes/taskRequest.js:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
var io = req.app.get('socketio');
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
//we only send the emit event to the pickedUser
io.to(pickedUser).emit('taskRequest', req.body);
io.on('connection', function (socket) {
console.log('connected 2');
socket.on('taskResponse', function () {
console.log('hello 2');
});
});
});
module.exports = router;
When a client is connected, I get the "connected" message in console, but not the "connected 2" message.
Also, when client emits "connected" message, I get "hello" in console, but when clients emits "taskResponse" message, I don't get "hello 2" in console.
Though when io.to(pickedUser).emit('taskRequest', req.body); is called, it works, client receives the "taskRequest" message.
Why is .emit() working inside my route but not .on() ?
According to you code, io is a Socket.IO server instance attached to an instance of http.Server listening for incoming events. Then inside the route you are again attaching a instance to listen to to incoming events which does not work. the io.to(pickedUser).emit works because the server instance with socketio is correctly listening to the connection thus giving the console.log("connected");.
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest');
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
app.set('socketio', io);
server.listen(4002);
routes/taskRequest.js:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
var io = req.app.get('socketio');
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
io.on('connection', function (socket) {
console.log('connected 2');
io.to(pickedUser).emit('taskRequest', req.body);
socket.on('taskResponse', function () {
console.log('hello 2');
});
});
});
module.exports = router;
I mark TRomesh answer as the right answer, since indeed you can only have one io.on('connection', function (socket) {}) in your code.
Now here is what I have done to make it work for me: the issue was that if you place io.on('connection', function (socket) {}) within your router.post('/', async (req, res) => {}), it will only be triggered when you call your endpoint. In my case, I had some sockets events that I wanted to be called at anytime, not only when the endpoint is called. So I had to place the io.on('connection', function (socket) {}) outside of my router.post('/', async (req, res) => {}). Thus I couldn't use var io = req.app.get('socketio'); inside the router. Here is what I have done instead:
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest')(io);
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
server.listen(4002);
routes/taskRequest.js
const express = require('express');
const router = express.Router();
module.exports = function(io) {
//we define the variables
var sendResponse = function () {};
io.sockets.on("connection",function(socket){
// Everytime a client logs in, display a connected message
console.log("Server-Client Connected!");
socket.on('connected', function(data) {
//listen to event at anytime (not only when endpoint is called)
//execute some code here
});
socket.on('taskResponse', data => {
//calling a function which is inside the router so we can send a res back
sendResponse(data);
})
});
router.post('/', async (req, res) => {
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
io.to(pickedUser).emit('taskRequest', req.body);
sendResponse = function (data) {
return res.status(200).json({"text": "Success", "response": data.data});
}
});
return router;
};

How do I transfer this local server API to a web API to deploy my app in heroku?

I have these code for a Chat App and it is only working in Local Server
I have already tried the following. Calling io() without any path arguments.
// Client Side Code
socket = io();
socket.connect({ query: `username=${props.username}` })
The above didnt work. The app runs but does not show other user's messages.
// Client Side Code
socket = io('http://myherokuapp:3001', { query:
`username=${props.username}` }).connect();
Neither did the above code work. The app crashed on this one.
Here is my actual source code:
// Server Side Code
const express = require("express");
const path = require("path");
const PORT = process.env.PORT || 3001;
const app = express();
const http = require("http");
const cors = require("cors");
const io = require("socket.io");
const server = http.createServer(app);
const socketIo = io(server);
app.use(cors());
app.get('/messages', (req, res) => {
res.sendFile(path.resolve('./public/index.html'));
});
socketIo.on('connection', socket => {
const username = socket.handshake.query.username;
console.log(`${username} connected`);
socket.on('client:message', data => {
console.log(`${data.username}: ${data.message}`);
socket.broadcast.emit('server:message', data);
});
socket.on('disconnect', () => {
console.log(`${username} disconnected`);
});
});
server.listen(PORT, () => {
console.log(`🌎 ==> API server now on port ${PORT}!`);
});
// Client Side Code
socket = io('http://localhost:3001', { query:
`username=${props.username}` }).connect();
socket.on('server:message', message => {
addMessage(message);
});
socket.emit('client:message', messageObject);
addMessage(messageObject);
I expect the chat app to be working same as it does in localhost.

nodejs cluster socket.io express app

var httpsport = 8080, // used for httpsapp
httpport = 8000, // used for httpapp
numCPUs = require('os').cpus().length;
var credentials = {
key: fs.readFileSync('./cert/client.key'),
cert: fs.readFileSync('./cert/client.crt'),
requestCert: true
};
var cluster = require('cluster'),
socketStore = require('socket.io-clusterhub');
var redis = require('redis');
var redisClient = redis.createClient();
if(cluster.isMaster) {
for(var i=0; i<numCPUs; i++) {
cluster.fork();
}
} else {
var io = require('socket.io'),
express = require('express'),
httpsapp = express(), // for https services
httpapp = express(), // for http services
http = require('http'),
https = require('https');
httpapp.configure( function () {
httpapp.use(express.bodyParser());
httpapp.use(express.methodOverride);
httpapp.use(httpapp.router);
httpapp.set('port', httpport);
httpapp.use(express.static(__dirname+'/public', {maxAge:oneDay}));
});
httpsapp.configure( function() {
// allow CORS
httpsapp.all('*', function(req, res, next){
if(!req.get('Origin')) {
return next();
}
// use "*" here to accept any origin
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Methods', 'GET');
res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
// res.set('Access-Control-Allow-Max-Age', 3600);
if ('OPTIONS' === req.method) {
return res.send(200);
}
next();
});
httpsapp.use(express.bodyParser());
httpsapp.use(express.static(__dirname + '/public'));
httpsapp.set('port', httpsport);
});
var httpServer = http.createServer(httpapp),
httpsServer = https.createServer(credentials, httpsapp),
sio = io.listen(httpServer);
// set the configuration for production.
sio.configure('production', function(){
sio.enable('browser client etag');
sio.set('log level', 1);
sio.set('store',socketStore);
sio.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]);
});
sio.of('/namespace1').on('connection', function(socket) {
socket.on('doSomething', function() {
socket.emit('reply',{hello:world}) });
httpsapp.get("/user", function(req, res) {
// ...
});
}
}
If node cluster is used, I'm getting the response: Cannot GET /user. But without cluster, it is able to service the https.get("/user").
Also, using cluster, I would like to check if the redis, http(s), socket.io and express module should be declare in the workers part or declare globally?
The httpsapp.get() is nested within the socket space because it would want to reply to the specific socket. Is there any way to get around this structure?
Anyone could figure our why httpsapp.get() is not servicing request?
And also where would those declaration be appropriate?
Thank you!

Categories