Socket IO forbidden 403 - websocket

I have a simple socket.io app and it works just fine on local and also it's installed successfully on AWS server using plesk admin dashboard but when I connect to the app I always get forbidden {"code":4,"message":"Forbidden"} .. the entry point seems to work great http://messages.entermeme.com .. any idea what could be wrong with it ?
Frontend code
import io from 'socket.io-client'
const socket = io('https://messages.entermeme.com', {
transports: ['polling'],
})
socket.emit('SUBSCRIBE')
Backend code
const cors = require('cors')
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server)
server.listen(9000)
app.use(cors())
io.set('transports', [
'polling'
])
io.origins([
'http://localhost:8000',
'https://entermeme.com',
])
io.on('connection', (socket) => {
socket.on('SUBSCRIBE', () => {
//
})
})

had a similar issue but when using nginx. So in case you still need some help:
In the end it turned out to be the URL I specified as socket origins. I didn't specify the port since the origin for me was also running on port 80 (443 for SSL) like in your example above:
io.origins([
'http://localhost:8000',
'https://entermeme.com', // <--- No port specified
])
I updated my config and added the port. So for you it would be:
io.origins([
'http://localhost:8000',
'https://entermeme.com:80', // <--- With port (or 443 for SSL)
])

Related

Getting "connect_error due to xhr poll error" while connecting socket server

I am trying to connect socket.io client which inside react app to the socket.io server but i am getting xhr poll error. I am unable to figure out what is going wrong? client & server code is as follow:
import io from 'socket.io-client';
const socket = io("ws://loacalhost:5000");
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
const express = require('express');
const app = express();
app.use(require('cors')());
const http = require('http');
const server = http.createServer(app);
const io = require("socket.io")(server, {
rejectUnauthorized: false,
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"]
}
})
io.on("connection", (socket) => {
console.log(socket.id)
})
server.listen(5000, () => {
console.log('Server is listening on Port 5000');
});
Everything is ok in server file as well as everything is ok in client file except there is syntax mistake in client code i.e.
const socket = io("ws://loacalhost:5000");
replaced with:
const socket = io("ws://localhost:5000");
then it is worked fine, successfully connected to server
Your localhost spelling is incorrect.
const socket = io("ws://loacalhost:5000");
Replaced with
const socket = io("ws://localhost:5000");

Can't emit from server to client and from client to server [Socket.io]

I'm creating my product and stuck with this problem. One day I setuped socket.io and everything worked well. On the next day I migrate my server and client from http to https. After the migration client side and server side still connected, but I can't emit from client side to server and from server to client.
Server side
I have my ssl certificate inside ./security/cert.key and ./security/cert.pem they are loading correctly. My server running on https://localhost:5000
import fs from "fs";
import https from "https";
import socketio from "socket.io";
import express from "express";
// HTTPS optiosn
const httpsOptions = {
key: fs.readFileSync("./security/cert.key"),
cert: fs.readFileSync("./security/cert.pem"),
};
// Setup express and https server
const app = express();
const server = https.createServer(httpsOptions, app);
// Setup socket io
const io = socketio.listen(server, {
origins: "https://localhost:3000",
transports: ["websocket"],
});
server.listen(5000, () => {
console.log(`server listening on https://localhost:5000`);
});
io.listen(server);
io.on("connection", (socket) => {
console.log("new socket connected!");
console.log(`data = ${socket.handshake.query.data}`);
socket.emit("some-event");
socket.on("some-event-2", () => console.log("some-event-2 happened!"));
});
Client Side
My example react component. My react app is running on https://localhost:3000. HTTPS is connected and working well.
import React from "react";
import io from "socket.io-client";
const Sandbox: React.FC = () => {
const query = {
"data": 123,
};
const socket = io.connect("https://localhost:5000", {
secure: true,
query,
transports: ["websocket"],
});
socket.on("connect", () => console.log("connect!"));
socket.on("some-event", () => console.log("some event happened"));
socket.emit("some-event-2");
return <React.Fragment />;
};
export default Sandbox;
And now the problem. On client side in console I should see connect! and some event happened
And on server side I should see the messages new socket connected! and data = 123, some-event-2 happened!. But instead my client side console is completely clear
And server side console have only a few logs, but dont contains emit logs
What should I do? Maybe I'm incorrectly using socket.io with https?
I fixed my error.
The problem was that I was firstly create https server and after that only call .listen() on it. listen() - is not a void, it's return another server obj. You need to pass the result of .listen() function inside your io.listen()
// Don't do that❌
var server = https.createServer(options, app);
server.listen(5000);
io.listen(server);
// Do that✅
var server = https.createServer(options, app).listen(5000);
io.listen(server);

Is there analog of express's app.set( 'something', something ) in koa?

I need socket.io instance in several places in my app. To achieve this in express i can do this:
app.set('io', io);
In koa right now i have this:
app.use( async ( ctx, next ) => {
ctx.io = io;
await next();
});
This works, but this middleware executes every time my server recieves request. Is there a better way to do this?
I don't know how you are fully implementing but there are a couple things that you can do is you can either pass an addition argument and upgrade the connection to a websocket that will bypass the rest of the middlewares. Or, what I do personally is just have any websocket connection go to a different end point. This will help with any future scalability issues. for example, if you need to create clusters of your server then you will have more control as well will help you testing your backend easier. That's what I would do atleast. My socket.io back end looks like this:
server.ts
oh yea I'm using typescript in the back end
require('dotenv').config({ path: __dirname + '/.env' });
import Koa from 'koa';
const koa = new Koa();
import cors from '#koa/cors';
const PORT = process.env.CHAT_PORT || 3000;
const ENV = process.env.NODE_ENV || 'development';
const server = require('http').createServer(app, { origins: 'http://server.ip' });
const io = (module.exports.io = require('socket.io')(server));
import SocketManager from './lib/SocketManager';
app.use(
cors({
origin: '*',
optionsSuccessStatus: 200,
}),
);
// server setup
server.listen(PORT, (err: ErrorEvent): void => {
if (err) console.error('❌ Unable to connect the server: ', err);
console.log(`💻 Chat server listening on port ${PORT} - ${ENV} environment`);
});
io.on('connection', SocketManager);
then just create a socket manager that imports the io instance and you can then go ahead and handle all the connections.
I hope this is the answer you were looking for/gave you some better insight.

Cannot hit simple node web server hosted on EC2 instance

Not able to hit my simple node web server hosted on an ubuntu EC2 in AWS. But I can't see I've missed anything! I've provided screen shots below within AWS - What am I missing? Please help!.
Many thanks,
Node code
const http = require('http');
const hostname = '127.0.0.1';
const port = 8080;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Command prompt
$ node index.js
Command prompt response
Server running at http://127.0.0.1:8080/
EC2 instance
Security settings
Elastic IP settings
Browser
http://"Public DNS (IPv4) value":8080/
Update
When you select the type, select "Custom TCP Rule":
and enter 8080 in the port range field.
EDIT
However, that only gets you part of the way. If you notice, your server is listening on the IP address 127.0.0.1. That means that it's not listen to the outside world, only localhost. To access it outside of the server machine you'll need to change your code to:
const http = require('http');
const hostname = '0.0.0.0';
const port = 8080;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
The change is that you're now listening on "all interfaces" as compared to just localhost.

Socket.io connection url?

I have the current setup:
Nodejs Proxy (running http-reverse-proxy) running on port 80.
Rails server running on port 3000
Nodejs web server running on port 8888
So any request starting with /nodejs/ will be redirected to nodejs web server on 8888.
Anything else will be redirected to the rails server on port 3000.
Currently Socket.io requires a connection url for io.connect.
Note that /nodejs/socket.io/socket.io.js is valid and returns the required socket.io client js library.
However, I am not able to specify connection_url to /nodejs/ on my server.
I have tried http://myapp.com/nodejs and other variants but I am still getting a 404 error with the following url http://myapp/socket.io/1/?t=1331851089106
Is it possible to tell io.connect to prefix each connection url with /nodejs/ ?
As of Socket.io version 1, resource has been replaced by path. Use :
var socket = io('http://localhost', {path: '/nodejs/socket.io'});
See: http://blog.seafuj.com/migrating-to-socketio-1-0
you can specify resource like this:
var socket = io.connect('http://localhost', {resource: 'nodejs'});
by default resource = "socket.io"
If you are using express with nodejs:
Server side:
var io = require('socket.io')(server, {path: '/octagon/socket.io'});
then
io.on('connection', function(socket) {
console.log('a user connected, id ' + socket.id);
socket.on('disconnect', function() {
console.log('a user disconnected, id ' + socket.id);
})
})
socket.on('publish message ' + clientId, function(msg) {
console.log('got message')
})
Client side:
var socket = io('https://dev.octagon.com:8443', {path: '/octagon/socket.io'})
then
socket.emit('publish message ' + clientId, msg)
I use below approach to achieve this goal:
client side:
var socket = io.connect('http://localhost:8183/?clientId='+clientId,{"force new connection":true});
server side:
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log("url"+socket.handshake.url);
clientId=socket.handshake.query.clientId;
console.log("connected clientId:"+clientId);
});
reference:https://github.com/LearnBoost/socket.io/wiki/Authorizing#global-authorization
If you are serving your app with express, then maybe you can check this out. Remember express uses http to serve your application.
const express = require('express'),
http = require('http'),
socketIo = require('socket.io'),
app = express()
var server = http.createServer(app);
var io = socketIo(server);
io.on('connection', (socket)=>{
// run your code here
})
server.listen(process.env.PORT, ()=> {
console.log('chat-app inintated succesfully')
})

Resources