call method
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);
}