I am having a server hosted in Heroku. Also, the client side(React) is hosted in Vercel. This combination works perfectly ! But, out of my curiosity, I tried to host the server-side script in Vercel. Then, when I try to connect to the Vercel-hosted-server, the client side is returning this error Access to XMLHttpRequest at 'https://socketio-vercel.vercel.app/socket.io/?EIO=4&transport=polling&t=NVeP_Ax' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. (I am testing in localhost:3000 )
Server-side code (both are same in Heroku and Vercel) ->
"use strict";
const express = require("express");
const socketIO = require("socket.io");
const PORT = process.env.PORT || 3000;
const INDEX = "/index.html";
const server = express()
.use((req, res) => res.sendFile(INDEX, { root: __dirname }))
.listen(PORT, () => console.log(`Listening on ${PORT}`));
const io = socketIO(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
console.log("Client connected");
socket.on("disconnect", () => console.log("Client disconnected"));
});
setInterval(() => io.emit("time", new Date().toTimeString()), 1000);
Client-side code (if server is hosted with Heroku) (Working) ->
useEffect(() => {
if (shouldStart) {
axios.get("api/sync").then((response) => {
setMessages(response.data);
const socket = io("wss://radiant-mountain-09008.herokuapp.com");
socket.on("connect", () => {
console.log("connected"); // "G5p5..."
});
socket.on("time", (msg) => {
console.log(msg);
});
});
}
}, [shouldStart]);
Client-side code (if server is hosted with Vercel) ->
useEffect(() => {
if (shouldStart) {
axios.get("api/sync").then((response) => {
setMessages(response.data);
const socket = io("wss://socketio-vercel.vercel.app");
socket.on("connect", () => {
console.log("connected"); // "G5p5..."
});
socket.on("time", (msg) => {
console.log(msg);
});
});
}
}, []);
Any idea why is this happening ?
Thanks !
as far I know vercel supports serverless function only. You can't use any socket, websocket Libraries. You can learn more details in this official link from their github. I hope this will help. Good luck
Related
Hello everyone and happy holidays!
I'm creating a chat app using socket.io and Express and need some guidance on how to proceed.
As it is now, I have my socket.io module in the same file as my express js file.
And it works fine, but when I started to implement a login page i noticed that when a go to the "localhost:port/" i still get connected to the socket and i get assigned a socket.id.
And it does make sense, I suppose, to start from the top and go to the bottom.
My plan is:
Go through the login page first
Then get redirected to the "localhost:port/MessagingClient" and get a socket.id
How it works now:
Go to the login page, get assigned a socket.id without login in.
Go to "localhost:port/MessagingClient" and get assigned a new socket.id
But since i run everything in 1 js file it doesn't work as i want it to.
My question is how can I split "Login" page and "MessagingClient" page, but still run on the same port?
I imagine I could solve this by running 2 node js processes instead of 1 and use 2 ports, but is that a valid way of doing it?
MessaginServer.js:
const dotenv = require("dotenv").config();
const express = require("express");
const app = require("express")();
const http = require("http").Server(app);
const io = require("socket.io")(http);
const port = process.env.PORT || 3000;
// import { readFromDB } from "./mongoDB.js";
const { readFromDB } = require("./mongoDB");
app.use(express.static(__dirname + "/public/"));
app.get("/", (req, res) => {
res.sendFile(__dirname + "/Public/LoginClient.html");
});
app.get("/MessagingClient", (req, res) => {
res.sendFile(__dirname + "/Public/MessaginClient.html");
});
io.on("connection", async (socket) => {
// socket.on("test1", arr1, arr2)=>{};
// socket.on("test2", arr1, arr2)=>{};
})
http.listen(port, () => {
console.log(`Socket.IO server running at http://localhost:${port}/`);
});
What i have tried:
I tried to move all the socket.io code inside
app.get("/MessagingClient", (req, res) => {
res.sendFile(__dirname + "/Public/MessaginClient.html");
});
but that resulted in message duplication..
Then I thought about trying to use Npm concurrently, but could not find anything about whether it is okay to use it in a production environment.
Any tips?
you create a socket server in a separate file:
const socketServer = (server) => {
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
//set middleware for socket server here before .on
io.use((socket, next) => {
yourMiddleware(socket, next);
});
// your io connection logic
io.on("connection", async (socket) => {
// socket.on("test1", arr1, arr2)=>{};
// socket.on("test2", arr1, arr2)=>{};
});
};
module.exports = {
socketServer,
};
then in app.js
//initialize app
const app = express();
// add your middlewares and routing
const server = http.createServer(app);
// import socketServer
socketServer(server);
server.listen(PORT, () => {
console.log(`Server is listening on ${PORT}`);
});
you create a socket server in a separate file:
const socketServer = (server) => {
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
//set middleware for socket server here before .on
io.use((socket, next) => {
yourMiddleware(socket, next);
});
// your io connection logic
io.on("connection", async (socket) => {
// socket.on("test1", arr1, arr2)=>{};
// socket.on("test2", arr1, arr2)=>{};
});
};
module.exports = {
socketServer,
};
then in app.js
//initialize app
const app = express();
// add your middlewares and routing
const server = http.createServer(app);
// import socketServer
socketServer(server);
server.listen(PORT, () => {
console.log(`Server is listening on ${PORT}`);
});
I have a problem with using socket.io in my application.
I use Next.js, Express.js, socket.io, socket.io-client
When I run Next.js server and Express server then access the page, socket is immediately connected. But when I post to /webhook/notify from other server socket.emit("notify", req.body); does not work. But when I reload the backend server, somehow it works for no reason.
Below are my codes
Frontend side
const socket = io.connect("http://127.0.0.1:3000", { cors: true }); //backend server
socket.on("connection", async (data) => { // it works
try {
console.log(data);
} catch (err) {
console.error(err.response);
}
});
socket.on("notify", async (notify) => { // it does not works while I reload backend server
try {
console.log(notify);
} catch (err) {
console.error(err.response);
}
});
Backend side
index.js
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors({ origin: "http://127.0.0.1:3060" }));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
const Socket = require("./socket");
const server = app.listen(PORT, function () {
return console.log("Backend server listening on port" + PORT);
});
Socket(server, app);
socket.js
const Socket = require("socket.io");
const axios = require("axios");
module.exports = (server, app) => {
const io = Socket(server, {
cors: {
origin: "*",
},
});
io.on("connection", (socket) => {
console.log("socket is connected");
app.post("/webhook/notify", (req, res, next) => {
try {
socket.emit("notify", req.body);
} catch (err) {
console.error(err.response);
return next(err);
}
});
socket.on("disconnect", () => {
console.log("disconnected");
});
});
};
I am attempting to create a server that will accept a post request (coming from a flutter app) containing the name of a song. I then want the server to broadcast the name of that song to all listening clients.
I've tried a dozen ways to do this and nothing seems to work. I've tried using express and flask, but to no avail. Here's where I'm at right now, but obviously this doesn't work because I can't get the script to start both the socket server (using npm start) and api (using node index.js) at the same time. You'll also notice that I'm not currently sending a song name, just trying to send a time to start.
'use strict';
const port = process.env.PORT || 3000;
const express = require('express');
const { Server } = require('ws');
const PORT = process.env.PORT || 3000;
const INDEX = '/index.html';
const server = express()
.use((req, res) => res.sendFile(INDEX, { root: __dirname }))
.listen(PORT, () => console.log(`Listening on ${PORT}`));
const wss = new Server({ server });
wss.on('connection', (ws) => {
console.log('Client connected');
ws.on('close', () => console.log('Client disconnected'));
});
setInterval(() => {
wss.clients.forEach((client) => {
client.send(new Date().toTimeString());
});
}, 1000);
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.post('/', (req, res) => {
wss.clients.forEach((client) => {
client.send(new Date().toTimeString());
});
res.send('POST request reached server');
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
I'm building a messaging feature with socket.io and a React frontend. With a socket.io only server it is working as expected, with the following code:
Socket.io server only
const io = require("socket.io")(5000, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
const id = socket.handshake.query.id;
socket.join(id);
socket.on("send-message", ({ recipients, text }) => {
recipients.forEach((recipient) => {
const newRecipients = recipients.filter((r) => r !== recipient);
newRecipients.push(id);
socket.broadcast.to(recipient).emit("receive-message", {
recipients: newRecipients,
sender: id,
text,
});
});
});
});
I am trying to integrate with express. The server is starting with the code below but messaging is no longer working:
Express server
const express = require("express");
const socketIo = require("socket.io");
const cors = require("cors");
const PORT = process.env.PORT || 5000;
const app = express();
const http = app.listen(PORT, () =>
console.log(`🚀 Server ready at http://localhost:${PORT}`)
);
const io = socketIo(http, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST", "send-message", "receive-message"],
},
});
io.once("connection", (socket) => {
const id = socket.handshake.query.id;
socket.join(id);
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
socket.on("send-message", ({ recipients, text }) => {
recipients.forEach((recipient) => {
const newRecipients = recipients.filter((r) => r !== recipient);
newRecipients.push(id);
socket.broadcast.to(recipient).emit("receive-message", {
recipients: newRecipients,
sender: id,
text,
});
});
});
});
Running it locally for both instances in Chrome with a window and another incognito window open on localhost:3000
As described here on('connection') event on client side not work. Change it to on('connect');
// server-side
io.on("connection", (socket) => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});
// client-side
socket.on("connect", () => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});
I have an Electron project initiated with VueCLI and a litle nodejs socket.io server, here's the server's file :
const http = require('http');
const express = require('express');
const socketio = require('socket.io');
const {
userJoin,
getCurrentUser,
userLeave,
getRoomUsers,
users
} = require('./utils/users');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// Run when client connects
io.on('connection', socket => {
console.log(`Connected tp ${socket.id}`)
app.get('/send-file', (req, res, next) => {
res.send('Sent')
})
socket.on('joinRoom', (args)=>{
console.log('joinroom')
})
// Runs when client disconnects
socket.on('disconnect', () => {
const user = userLeave(socket.id);
});
});
const PORT = process.env.PORT || 7575;
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
And here's my preload.js file :
const io = require('socket.io-client');
window.socket = io('http://localhost:7575');
window.socket.on('welcome', () => {
console.log('on welcome : welcome received renderer'); // displayed
window.socket.emit('test')
});
window.socket.on('error', (e) => {
console.log(e); // displayed ?
});
window.socket.on('ok', () => {
console.log("OK received renderer"); // displayed
});
window.socket.on('connect', () => {
console.log("connected renderer"); // displayed
window.socket.emit('test');
});
And here's my createWindow function:
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 700,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
enableRemoteModule: true,
preload: path.join(__dirname, 'preload.js')
}
})
win.setMenu(null)
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
The connection is made between the client and the server, because the console.log(Connected tp ${socket.id}) show a different socket ID everytime, but on my compenent, when I call the emit function nothing happens : window.socket.emit('joinRoom', {email:this.email, apikey:this.apikey})
And I can't event receive message on the client side, I've tested the server and everything works fine on a normale browser, but on my electron application can't emit or receive messages.
Is this related to my electron application?
Here's how I did it -
Server side:
const express = require('express')
const app = express()
// middlewares
app.use(express.static('public'))
// routes
app.get('/', (req, res) => {
res.render('index')
})
server = app.listen(7575, () => {
console.log("Server started");
})
//socket.io instantiation
const io = require("socket.io")(server)
//listen on every connection
io.on('connection', (socket) => {
console.log('New user connected');
//listen on "test"
socket.on('test', (data) => {
var username = data.username;
})
})
Client side:
socket = io.connect('http://localhost:7575')
socket.emit('test', {username: 'username'})