5
votes

What I am trying to achieve?

To setup socket.io on my ec2 instances, with Nginx as the web server, with an AWS Application Load Balancer, and Route53 that resolves the DNS to point to my Application Load Balancer.

Here are the list of solutions that I found online that I have tried:

  1. Use Network load balancer instead with TCP 80, and TCP 443, and SSL at the application level. The client socket connect url would be https://mydomain:9000 and I keep getting error websocket connection closed before connection could be established.. The target group has stickiness enabled.

  2. Use Application Load Balancer, and add a path based rule to my listener for path /socket.io and forward it to a different target group with stickiness enabled: Now I tried both 443 protocol and 9000 port with HTTPS protocol. I got same result.

  3. Use the public DNS of my load balancer as the url for the socket client connection. And still same result.

Here's my nginx config file:

    # SSL configuration

     listen 443 ssl default_server;
     listen [::]:443 ssl default_server;

    ssl_certificate  /path/to/ssl.crt;
    ssl_certificate_key /path/to/private_key.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    if ($ssl_protocol = "") {
  rewrite ^   https://$server_name$request_uri? permanent;
}

    server_name _;

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-NginX-Proxy true;
    proxy_pass http://localhost:9000;

    }

Now, I should let you know that I have forced socket client to use websocket transport, xhr-polling was giving me the following error, which again I have no idea what to do with it.

Failed to load https://my_domain/socket.io/?EIO=3&transport=polling&t=M3lhVWi: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4444' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

If someone can help me with either of the situation that would establish a socket connection, then I'd be really thankful. Also, please ask if you need any other relevant information.

Edit Here's how I setup my socket.io

const app = express();

const server = http.createServer(app);

const socketio = io(server, {
    serveClient: false,
    pingInterval: 10000,
    pingTimeout: 5000,
    cookie: false,
    transport: ['websocket', 'xhr-polling']
});

socketConfig(socketio);

//and here's socketConfig

export function socketConfig(socketio) {
    let localSockets = [];
    socketio.on('connection', connectConfig(socketio, localSockets))
}

Update: A stupid mistake on my part, although this didn't solve my problem, the client connection url would be https://mydomain since the socket.io and my nodejs server are listening on the same port. I am using Application Load Balancer now, and I am getting 502 error.

Update: I checked my Nginx error logs and found this:

upstream prematurely closed connection while reading response header from upstream, client: 172.31.11.251, server: _, request: "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1", upstream: "http://127.0.0.1:9000/socket.io/?EIO=3&transport=websocket", host: "mydomain"
1
I have faced similar issue. we have replaced ourdomain with wss://ourdomain while connection from client side : io.connect('wss://ourdomain', {path:'<your_application_route_if_you_have_any>/socket.io' })Dhaval Chaudhary
But socket.io handles that automatically, anyway, it didn't work.relentless-coder
if you can share your server side configuration so that i can try it out.Dhaval Chaudhary
@DhavalChaudhary kindly check the edit, I have updated it with required detailsrelentless-coder

1 Answers

0
votes

Okay, I fixed it and it was a super silly mistake on my part:

I had this in my code:

app.listen(config.port, config.ip, () => {
    console.log(`express server listening on port ${config.port} in ${config.env} mode`);
});

instead of:

server.listen(config.port, config.ip, () => {
    console.log(`express server listening on port ${config.port} in ${config.env} mode`);
});