Future<WebSocket> upgradeToWebSocket(HttpRequest request, [ dynamic protocolSelector(List<String> protocols), bool useStandardWebSocket ])

Source

static Future<WebSocket> upgradeToWebSocket(HttpRequest request, [
  protocolSelector(List<String> protocols),
  bool useStandardWebSocket
]) {
  if (useStandardWebSocket == null) {
    useStandardWebSocket = enableStandardWebSocket;
  }

  if (useStandardWebSocket) {
    return WebSocketTransformer.upgrade(
      request,
      protocolSelector: protocolSelector
    );
  }

  var response = request.response;
  if (!WebSocketTransformer.isUpgradeRequest(request)) {
    // Send error response.
    response
      ..statusCode = HttpStatus.BAD_REQUEST
      ..close();
    return new Future.error(
      new WebSocketException("Invalid WebSocket upgrade request"));
  }

  Future<WebSocket> upgrade(String protocol) {
    // Send the upgrade response.
    response
      ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
      ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
      ..headers.add(HttpHeaders.UPGRADE, "websocket");
    String key = request.headers.value("Sec-WebSocket-Key");
    String accept = BASE64.encode(
      sha1.convert("$key$_webSocketGUID".codeUnits).bytes
    );
    response.headers.add("Sec-WebSocket-Accept", accept);
    if (protocol != null) {
      response.headers.add("Sec-WebSocket-Protocol", protocol);
    }
    response.headers.contentLength = 0;
    return response.detachSocket()
      .then((socket) {
      socket.setOption(SocketOption.TCP_NODELAY, _tcpNoDelay);
      return new WebSocket.fromUpgradedSocket(
        socket, protocol: protocol, serverSide: true);
    });
  }

  var protocols = request.headers['Sec-WebSocket-Protocol'];
  if (protocols != null && protocolSelector != null) {
    // The suggested protocols can be spread over multiple lines, each
    // consisting of multiple protocols. To unify all of them, first join
    // the lists with ', ' and then tokenize.
    protocols = HttpHelper.tokenizeFieldValue(protocols.join(', '));
    return new Future(() => protocolSelector(protocols)).then((String protocol) {
      if (protocols.indexOf(protocol) < 0) {
        throw new WebSocketException(
          "Selected protocol is not in the list of available protocols");
      }
      return protocol;
    }).catchError((error) {
      response
        ..statusCode = HttpStatus.INTERNAL_SERVER_ERROR
        ..close();
      throw error;
    }).then((result) {
      if (result is String) {
        return upgrade(result);
      }
      return null;
    }).then((WebSocket socket) {
      return socket;
    });
  } else {
    return upgrade(null);
  }
}