rikulo / socket.io-client-dart

socket.io-client-dart: Dartlang port of socket.io-client https://github.com/socketio/socket.io-client
https://quire.io
MIT License
674 stars 185 forks source link

Solution for https and reverse proxy - WORKS #319

Open markosole opened 1 year ago

markosole commented 1 year ago

Hi all,

After 3 days of searching and digging around, I've finally made compatible (mixture) setup between NodeJS Server + Client + Flutter client that work over HTTPS. Many of you had or still have same problem and here is short and sweet how to set it up with Apache reverse proxy forwarding

Server

Short and simple

const express = require('express');
const app = express();
const http = require("http").createServer(app);
socketio = require("socket.io")(http);

http.listen(5003, () => console.log('Socket server served on port: 5003'));

NodeJS Client

Works with https with transports set to polling and without specified port number. Sidenote: NodeJS client does not work with websocket transports. It has to be set to "polling" mode or not set at all (default is polling)


var ios = require('socket.io-client');
var socketClient = ios.connect('https://domain.com', {
    reconnect: true,
    secure: true,
    rejectUnauthorized : false,
    transports: ['polling']

});

Flutter Client

Works with http and on specified port:

IO.Socket socket = IO.io('http://domain.com:5003',  
    OptionBuilder()  
        .setTransports(['websocket'])  
        .build());  

socket.connect();

Works with HTTPS:

IO.Socket socket = IO.io('https://domain.com',  
    OptionBuilder()  
        .setTransports(['websocket'])  
        .build());  

socket.connect();

Apache config - common setups

This does not work for Flutter client on https. Use another one below.

    ProxyPass / http://127.0.0.1/
    RewriteEngine on
    RewriteCond %{HTTPS:Upgrade} =websocket
    RewriteRule /(.*) "http://127.0.0.1:5003/$1" [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket
    RewriteRule /(.*) "http://127.0.0.1:5003/$1" [P,L]

Apache config - Flutter compatible

Keep in mind to add ws:// instead http:// as on example above

    RewriteEngine On    
    # Needed for Flutter app
    RewriteRule /(.*)           ws://localhost:5003/$1 [P,L]

    # Needed for NodeJS clients
    ProxyPass / http://localhost:5003/
    ProxyPassReverse / http://localhost:5003/

Versions used

NodeJS socket.io server: 4.6.0 NodeJS socket.io-client: 4.6.0 Flutter socket_io_client package: 2.0.1

Drop a comment if you have questions and suggestions. Cheers

sametserpil commented 1 year ago

@markosole Hello. How can I edit rules for Nginx? I can connect my remote server socket via javascript client but not via Flutter.

markosole commented 1 year ago

@sametserpil is your server Apache or Nginx and do you have access to config? - I am not Apache (and even less Nginx) expert but I'll try to help.

sametserpil commented 1 year ago

Yeah server is mine and I've setup Nginx for reverse proxy. It's also not working with ip:port combination. Here are my logs:

My NodeJS socket.io version -> "socket.io": "^4.6.1", My Flutter socket.io client version -> socket_io_client: ^2.0.1

opening https://my-host-url-here I/flutter ( 9768): FINE: 2023-03-07 14:47:11.806365: creating transport "polling" I/flutter ( 9768): FINE: 2023-03-07 14:47:11.813039: setting transport websocket I/flutter ( 9768): FINE: 2023-03-07 14:47:11.814809: connect attempt will timeout after 20000 I/flutter ( 9768): FINE: 2023-03-07 14:47:11.956447: socket close with reason: "transport close"

markosole commented 1 year ago

Can you paste your:

  1. Ngix configuration
  2. Flutter socket connection part
  3. Node JS server / Client connection part of the code

It's missconfiguration or missmatch of versions.

sametserpil commented 1 year ago

Found the solution. It works with following nginx configuration and manual connection. @markosole thanks for the help.

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;

      proxy_pass http://localhost:3000;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
ROBERT-MCDOWELL commented 1 year ago

@sametserpil what's the equivalent for apache?

jumperchen commented 1 year ago

FYI:

Jimesh843 commented 10 months ago

Connection Error: WebSocketException: Connection to 'https://example.com:0/socket.io/?EIO=4&transport=polling#' was not upgraded to websocket

I am facing same issue. I have used socket_io_client: ^2.0.3+1 and from backend i have used 4.7.3 version of node and i have also set code necessary for server. but still can't connect

jumperchen commented 10 months ago

@Jimesh843 transport=polling only supports under web environment.

Jimesh843 commented 10 months ago

then i need to use transport as websocket instaed of pooling?

socket = IO.io( 'https://example.com', <String, dynamic>{ 'autoConnect' : false, 'transports' : ['websocket'], 'extraHeaders': {'foo': 'bar'}, }, );

is it relevant?

Output: Connection Error: WebSocketException: Connection to 'https://example.com:0/socket.io/?EIO=4&transport=websocket#' was not upgraded to websocket

Still I am getting this error should i need to give any thing on server side or any permission from my side

Jimesh843 commented 10 months ago

then i need to use transport as websocket instaed of pooling?

socket = IO.io( 'https://example.com', <String, dynamic>{ 'autoConnect' : false, 'transports' : ['websocket'], 'extraHeaders': {'foo': 'bar'}, }, );

is it relevant?

Output: Connection Error: WebSocketException: Connection to 'https://example.com:0/socket.io/?EIO=4&transport=websocket#' was not upgraded to websocket

Still I am getting this error should i need to give any thing on server side or any permission from my side

Please help to solve this issue