Custom WebSocket Connection logic.
Source
static Future<WebSocket> connectToWebSocket( String url, { Iterable<String> protocols, Map<String, dynamic> headers, HttpClient httpClient, bool useStandardWebSocket }) async { Uri uri = Uri.parse(url); if (useStandardWebSocket == null) { useStandardWebSocket = enableStandardWebSocket; } if (useStandardWebSocket == true && uri.scheme != "wss") { return await awaitWithTimeout(WebSocket.connect( url, protocols: protocols, headers: headers ), 60000, onSuccessAfterTimeout: (WebSocket socket){ socket.close(); }); } if (uri.scheme != "ws" && uri.scheme != "wss") { throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'"); } Random random = new Random(); // Generate 16 random bytes. Uint8List nonceData = new Uint8List(16); for (int i = 0; i < 16; i++) { nonceData[i] = random.nextInt(256); } String nonce = BASE64.encode(nonceData); int port = uri.port; if (port == 0) { port = uri.scheme == "wss" ? 443 : 80; } uri = new Uri( scheme: uri.scheme == "wss" ? "https" : "http", userInfo: uri.userInfo, host: uri.host, port: port, path: uri.path, query: uri.query ); HttpClient _client = httpClient == null ? ( new HttpClient() ..badCertificateCallback = (a, b, c) => true ) : httpClient; return _client.openUrl("GET", uri).then((HttpClientRequest request) async { if (uri.userInfo != null && !uri.userInfo.isEmpty) { // If the URL contains user information use that for basic // authorization. String auth = BASE64.encode(UTF8.encode(uri.userInfo)); request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth"); } if (headers != null) { headers.forEach((field, value) => request.headers.add(field, value)); } // Setup the initial handshake. request.headers ..set(HttpHeaders.CONNECTION, "Upgrade") ..set(HttpHeaders.UPGRADE, "websocket") ..set("Sec-WebSocket-Key", nonce) ..set("Cache-Control", "no-cache") ..set("Sec-WebSocket-Version", "13"); if (protocols != null) { request.headers.add("Sec-WebSocket-Protocol", protocols.toList()); } return request.close(); }).then((response) { return response; }).then((HttpClientResponse response) { void error(String message) { // Flush data. response.detachSocket().then((Socket socket) { socket.destroy(); }); throw new WebSocketException(message); } if (response.statusCode != HttpStatus.SWITCHING_PROTOCOLS || response.headers[HttpHeaders.CONNECTION] == null || !response.headers[HttpHeaders.CONNECTION].any( (value) => value.toLowerCase() == "upgrade") || response.headers.value(HttpHeaders.UPGRADE).toLowerCase() != "websocket") { error("Connection to '$uri' was not upgraded to websocket"); } String accept = response.headers.value("Sec-WebSocket-Accept"); if (accept == null) { error("Response did not contain a 'Sec-WebSocket-Accept' header"); } List<int> expectedAccept = sha1.convert("$nonce$_webSocketGUID".codeUnits).bytes; List<int> receivedAccept = BASE64.decode(accept); if (expectedAccept.length != receivedAccept.length) { error("Response header 'Sec-WebSocket-Accept' is the wrong length"); } for (int i = 0; i < expectedAccept.length; i++) { if (expectedAccept[i] != receivedAccept[i]) { error("Bad response 'Sec-WebSocket-Accept' header"); } } var protocol = response.headers.value('Sec-WebSocket-Protocol'); return response.detachSocket().then((socket) { socket.setOption(SocketOption.TCP_NODELAY, _tcpNoDelay); return new WebSocket.fromUpgradedSocket( socket, protocol: protocol, serverSide: false ); }); }).timeout(new Duration(minutes: 1), onTimeout:(){ _client.close(force: true); throw new WebSocketException('timeout'); }); }