dart-lang / web_socket_channel

StreamChannel wrappers for WebSockets.
https://pub.dev/packages/web_socket_channel
BSD 3-Clause "New" or "Revised" License
419 stars 109 forks source link

WebSocketException: Connection not upgraded to websocket #321

Open austin047 opened 8 months ago

austin047 commented 8 months ago

I am attempting to connect to a WebSocket API delivered via the AWS API gateway, currently, I am able to establish a successful connection via PostMan and Python scripts ran from my local terminal, but when I attempt a connection with dart I keep getting this error of WebSocketException: Connection was not upgraded to websocket

My code

main() async {
  final wsUrl = Uri.parse('wss://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/qa');
  final channel = IOWebSocketChannel.connect(wsUrl);

  // await channel.ready;

  channel.stream.listen((message) {
    print(message);
    channel.sink.add('received!');
  });
}

Error:

Unhandled exception:
WebSocketChannelException: WebSocketChannelException: WebSocketException: Connection to 'https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com:0/qa#' was not upgraded to websocket
#0      new IOWebSocketChannel._withoutSocket.<anonymous closure> (package:web_socket_channel/io.dart:98:24)
#1      Stream.handleError.<anonymous closure> (dart:async/stream.dart:931:16)
#2      _HandleErrorStream._handleError (dart:async/stream_pipe.dart:269:17)
#3      _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
#4      _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10)
#5      _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358:15)
#6      _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:376:7)
#7      _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#8      _SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:788:19)
#9      _StreamController._addError (dart:async/stream_controller.dart:666:7)
#10     _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10)
#11     _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358:15)
#12     _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:376:7)
#13     _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#14     _SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:788:19)
#15     _StreamController._addError (dart:async/stream_controller.dart:666:7)
#16     new Stream.fromFuture.<anonymous closure> (dart:async/stream.dart:253:18)
#17     _RootZone.runBinary (dart:async/zone.dart:1666:54)
#18     _FutureListener.handleError (dart:async/future_impl.dart:177:22)
#19     Future._propagateToListeners.handleError (dart:async/future_impl.dart:858:47)
#20     Future._propagateToListeners (dart:async/future_impl.dart:879:13)
#21     Future._completeError (dart:async/future_impl.dart:655:5)
#22     Future._asyncCompleteError.<anonymous closure> (dart:async/future_impl.dart:745:7)
#23     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#24     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
#25     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#26     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:405:11)
#27     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
#28     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

Any help on this will be much appreciated

Avril1 commented 8 months ago

Please check your server is opening first. I had the same issue, finally I found that the server was closed.

austin047 commented 8 months ago

My server in current up and running, I am able to create a websocket connection via the Postman client and a python script, but not Dart.

Avril1 commented 8 months ago

Have you tried this way? I'm using WebSocketChannel.connect(wsUrl).

austin047 commented 8 months ago

Yes I have tried that before, it's work aswell.

pnprogentec commented 4 months ago

Any update on this? I'm currently facing this issue.

Judimax commented 4 months ago

@pnprogentec for socket connections use socket_io_client: ^2.0.3+1 im refactoring peerdart library with chaptgpt when it suggested to use web_socket_channel but this whole time I have been using socket_io_client example usage ``` void start(String id, String token) async { _id = id; final version = await getVersion(); final wsUrl = '$_baseUrl&id=$id&token=$token&version=$version';

if (_socket != null || !_disconnected) {
  return;
}

_socket = IO.io(
    wsUrl,
    IO.OptionBuilder()
        .setTransports(['websocket'])
        .disableAutoConnect()
        .build());
_disconnected = false;
logger.log('WebSocket connection established.');

_socket!.on('connect', (_) {
  logger.log('Socket connected');
  _disconnected = false;
  _sendQueuedMessages();
  _scheduleHeartbeat();
});

_socket!.on('message', (message) {
  try {
   //if indeed the server sent json
    final data = jsonDecode(message);
    logger.log('Server message received: $data');
    emit(SocketEventType.Message.value, data);
  } catch (e) {
    logger.log('Invalid server message $message');
  }
});

_socket!.on('disconnect', (_) {
  if (_disconnected) {
    return;
  }

  logger.log('Socket closed.');
  _cleanup();
  _disconnected = true;
  emit(SocketEventType.Disconnected.value);
});

_socket!.on('error', (error) {
  emit(SocketEventType.Error.value, error);
});

_socket!.connect();
_sendQueuedMessages();
logger.log('Socket open');
_scheduleHeartbeat();

}

MaviaZindani commented 3 weeks ago

Finally! After a week of research I finally found a working solution:

I put this code into the Section of my Apache2 config:

    ProxyRequests off
    ProxyVia on
    RewriteEngine On

    RewriteEngine On
    RewriteCond %{HTTP:Connection} Upgrade [NC]
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteRule /(.*) ws://127.0.0.1:8080/$1 [P,L]

    ProxyPass               / http://127.0.0.1:5000/
    ProxyPassReverse        / http://127.0.0.1:5000/

   There's a million configurations out there and I tried them all - this is the only one that worked for me. The problem was, that Apache2 didn't forward the "Upgrade=websocket" and "Connection=upgrade" headers. The given rewrite commands make Apache2 add these headers to the proxied connection.

While researching this I first found a working Nginx configuration which I then translated to Apache2. So if you have that problem with Nginx, you can use this here:

This little NodeJS TCP Server helped me a lot with debugging the HTTP headers: https://riptutorial.com/node-js/example/22405/a-simple-tcp-server