简体   繁体   中英

Establish web-socket communication with react and express (nginx, docker)

Tried to setup the websocket connection and it worked fine when i was on local host environment, however once i've setup the docker envrionment, the client(react) has a hard time to establish web-socket communication with express. What url should i define to have web-socket open between the 2? i've tried http:/api or http://localhost:3050 but none of them were successful

This is my nginx.conf file

upstream client {
    server client:3000;
}

upstream api {
    server api:8080;
}

server{

    listen 80;

    location / {
        proxy_pass http://client;
    }

    location /socket.io {
        proxy_pass http://api;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

    location /api{
        rewrite /api/(.*) /$1 break;
        proxy_pass http://api;
    }
}

and this my docker compose

version: "3"
services:
  nginx:
    restart: always
    image: coco/nginx
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    ports:
      - "3050:80"
  api:
    image: coco/server
    build:
      dockerfile: Dockerfile.dev
      context: ./server
    volumes:
      - /app/node_modules
      - ./server:/app
  client:
    image: coco/client
    build:
      dockerfile: Dockerfile.dev
      context: ./client
    volumes:
      - /app/node_modules
      - ./client:/app

The key problem is in react container which requires to setup the websocket itself with this line of code const socket = socketIOClient("http:/api");, When it was on localhost it worked fine, and now when i start docker-compose, it fails. However the server is able to recieve axios calls etc, its just the web-socket cant be establishd from client

in my app.js file i have this

// configuring the port which is from config folder
let server = app.listen(config.port, function (err) {
    if (err) throw err;
    console.log("Server started on port " + config.port);
});

const io = require('socket.io').listen(server)
require('./routes/routes')(app, io)

In my react component i have a button, and when pressed it executes the following logic

  const socket = socketIOClient("http://api");
    socket.on("connect", () => {
      console.log("Socket Connected");
      socket.on("tweets", data => {
       console.log(data)
      });
    });

but it doesnt display anything nor it connects to anything

UPDATE:

At one point it worked without changing much and then it froze, i've added a few lines of code trying to debug it

 socket.on("error", function(err) {
        console.log("Socket.IO Error");
        console.log(err); // this is changed from your code in last comment
      });

it and thats what i found

Socket.IO Error
 Invalid namespace

If anyone faces this issue ever again, here is the solution

1) Specifying path for production in socket.io instance

const socket = socketIOClient({ path: "/socket.io" });

2) Inside of nginx, need to confugre routing

location /socket.io {
    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 $host;
    proxy_pass http://api/socket.io/;
}

Note: location is identical to specified path in socketIOClient from previous step. Then, proxy_pass: is reffering to the server itself with /socket.io

Hope it helps someone

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM