expressnginxsocket.ioexpress-gateway

Configuration Error Nginx + ExpressGateway + Express API + Socket.io


I'm having very difficult times trying to make this work, I have a microservice architecture in place that support multiple areas of the business, now I would like to add a new microservice that will expose a socket connection to serve some realtime information to the apps. Check the image below:

app architecture

I will share some aspects here to see if you can help me to fix this configuration issue.

I did some tests to identify where the issue is being caused, I did a test connecting directly to the Node API (running on the server) without using the Nginx and the ExpressGateway, check the Gif below everything works as expected:

See how it worked

It makes the 'polling' connection and then upgrade to Websocket that is what we want, received the messages and not make any new connections.

This is the API server configuration:

constructor() {
        this.app = express();
        this.initExpress();
        this.initExpressMiddleWare();
        this.dvConn = new DAO();
        this.server = this.start();
        this.io = io().attach(this.server, {
            path: `${config.BASE_PATH}`,
            origins: '*:*',
            transports:['polling', 'websocket'],
            serveClient: false
        });
        this.newSocketUsers = [];
        this.io.on('connection', (socket) => {
            console.log(`a user connected ${socket.id}`);
            const user_id = this.decode_id(socket.handshake.query.user_id).toString();
            const socket_id = socket.id;
            this.registerConnection(socket_id, user_id);
            socket.on('disconnect', () => {
                console.log(`a user disconnected ${socket.id}`);
                const socket_id = socket.id;
                this.unRegisteredConnection(socket_id);
            });
        });

And this is the part of an Angular client App to test this:

constructor(private http: HttpClient) {
    this.httpClient = http;
    this.socket = io('http://dev.server.com:3033', {
      query: {
        user_id: '988379518723645912'
      },
      transports: ['polling', 'websocket']
    });
    this.socket.on('reconnect_attempt', () => {
      this.socket.io.opts.transports = ['polling', 'websocket'];
    });
  }

  connect(): void {
    this.socket.on('connect', () => {
      console.log('Opening Connection');
    });
  }

Now the problem comes when this run through Nginx and the ExpressGateway, see the Gif below to see how the application first logs a 502 error, and it continues polling and never upgrade to WebSocket, making that with every new message sent it logs that as a new polling request:

See how it doesn't worked

I did my homework and I know some configuration is needed on Nginx, this is my Nginx.conf configuration:

server {
        listen 443 ssl;
        client_max_body_size 12m;
        client_body_buffer_size 16k;
        server_name dv3.synth5.orcasnet.com api.orcasnet.com;
        ssl_certificate /etc/nginx/ssl/certificate.crt;
        ssl_certificate_key /etc/nginx/ssl/key.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCMsssssss';
        location /  {
                proxy_temp_file_write_size 64k;
                proxy_connect_timeout 10080s;
                proxy_send_timeout 10080;
                proxy_read_timeout 10080;
                proxy_buffer_size 64k;
                proxy_buffers 16 32k;
                proxy_busy_buffers_size 64k;
                proxy_redirect off;
                proxy_request_buffering off;
                proxy_buffering off;
                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://gateway.domain.net:3020;
        }
}

And the last is the ExpressGateway policy configuration:

socStg:
    apiEndpoints:
      - socStg
    policies:
      - cors:
      - log:
        - action:
            message: ${req.method} ${req.originalUrl} ${req.headers}
      - proxy:
          - action:
              serviceEndpoint: socStg
              changeOrigin: true
              ws: true
              timeout: 120000

I would appreciate any help you can provide me with this problem, Thanks in advance.


Solution

  • Simple answer Express-Gateway doesn't support socket connections, I needed to deploy the API directly with Nginx. Now is working.