8000 WebSocket.connect() fails to proxy ws:// requests properly (426), but works with wss:// · Issue #1776 · dart-lang/http · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
WebSocket.connect() fails to proxy ws:// requests properly (426), but works with wss:// #1776
Open
@NotMeanttoBe

Description

@NotMeanttoBe

Summary

flutter --version
Flutter 3.29.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision c236373904 (2 months ago) • 2025-03-13 16:17:06 -0400
Engine • revision 18b71d647a
Tools • Dart 3.7.2 • DevTools 2.42.3

web_socket_channel: ^3.0.3

WebSocketException: Connection to 'http://example.com:80?token=xxx#' was not upgraded to websocket, HTTP status code: 426

When using WebSocket.connect() with a proxy and a ws:// (non-secure WebSocket) URL, Dart fails to perform a valid WebSocket handshake — the server responds with HTTP 426. The same code works fine with wss:// URLs through the proxy.
The proxy is a standard HTTP proxy (like Clash or Xray).
I verified that curl -x 127.0.0.1:10809 with proper headers works correctly with ws:// over the same proxy.

I have confirmed that the proxy configuration (such as Clash/Xray on localhost 127.0.0.1:10809) works correctly and can successfully proxy ws:// requests. On all platforms — including Android native, iOS, and Windows — the WebSocket handshake completes successfully when using tools like curl, browsers, or Java clients. Only Dart’s WebSocket.connect() fails with a 426 error when attempting to connect via ws:// through a proxy.

Code to reproduce

void connect() async {
    try {
      wsStatusListener.onConnecting?.call();

      final httpClient = HttpClient();

      httpClient.findProxy = (uri) {
        final proxy = "PROXY 127.0.0.1:10809;";
        return proxy;
      };

      final uri = Uri.parse(url);
      final socket = await WebSocket.connect(
        uri.toString(),
        customClient: httpClient,
      );

      _channel = IOWebSocketChannel(socket);

      _channel!.stream.listen(
        (message) {
          _handleMessage(message);
        },
        onError: (error) {
          _handleError(error);
        },
        onDone: () {
          _handleDone();
        },
      );

      _reconnectTimer?.cancel();
      _reconnectTimer = null;

      _isConnected = true;
      _startHeartbeat();
      _sendFlushMessageQueue();

      wsStatusListener.onConnected?.call();
    } catch (ex) {
      _isConnected = false;
      _handleError(ex);
    }
  }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0