call method

Future<void> call(
  1. Context context
)

Coverts the WebSocket to a Handler.

Implementation

Future<void> call(Context context) async {
  final request = context.request;
  if (!isWebSocketProtocolConnection(request)) {
    return fallback?.call(context) ?? _defaultFallback(context);
  }

  // validate protocol and web socket version
  _validateProtocol(request);

  final signatureKey = getWebSocketSignatureKeyOrThrow(request);
  final socket = await _detachSocket(context);

  // Gets the web socket sink and adds handshake headers.
  final sink = context.app.encoding.encoder.startChunkedConversion(socket)
    ..add(
      'HTTP/1.1 101 Switching Protocols\r\n'
      'Upgrade: websocket\r\n'
      'Connection: Upgrade\r\n'
      'Sec-WebSocket-Accept: $signatureKey\r\n',
    );

  // Chooses the protocol.
  final protocol = _chooseProtocol(request);

  // If the protocol is not null, then add it to the response headers.
  if (protocol != null) {
    sink.add('Sec-WebSocket-Protocol: $protocol\r\n');
  }

  // If the app is powered by, then add it to the response headers.
  if (context.app.poweredBy != null) {
    sink.add('X-Powered-By: ${context.app.poweredBy}\r\n');
  }

  // Ends the web socket handshake.
  sink.add('\r\n');

  final streamChannel = StreamChannel(socket, socket);
  final webSocketChannel = WebSocketChannel(
    streamChannel,
    protocol: protocol,
    pingInterval: pingInterval,
    serverSide: true,
  );

  // Awaits for the web socket channel to be ready.
  await webSocketChannel.ready;

  // Calls the web socket handler.
  await onConnection(context, webSocketChannel);

  // Awaits for the web socket channel to be done.
  await socket.done;

  // Closes the web socket connection.
  //
  // Note: The connection has been closed, tell Spry not to do anything here.
  return context.response.close(onlyCloseConnection: true);
}