in lib/src/web_socket_handler.dart [28:84]
Response handle(Request request) {
if (request.method != 'GET') return _notFound();
final connection = request.headers['Connection'];
if (connection == null) return _notFound();
final tokens =
connection.toLowerCase().split(',').map((token) => token.trim());
if (!tokens.contains('upgrade')) return _notFound();
final upgrade = request.headers['Upgrade'];
if (upgrade == null) return _notFound();
if (upgrade.toLowerCase() != 'websocket') return _notFound();
final version = request.headers['Sec-WebSocket-Version'];
if (version == null) {
return _badRequest('missing Sec-WebSocket-Version header.');
} else if (version != '13') {
return _notFound();
}
if (request.protocolVersion != '1.1') {
return _badRequest('unexpected HTTP version '
'"${request.protocolVersion}".');
}
final key = request.headers['Sec-WebSocket-Key'];
if (key == null) return _badRequest('missing Sec-WebSocket-Key header.');
if (!request.canHijack) {
throw ArgumentError('webSocketHandler may only be used with a server '
'that supports request hijacking.');
}
// The Origin header is always set by browser connections. By filtering out
// unexpected origins, we ensure that malicious JavaScript is unable to fake
// a WebSocket handshake.
final origin = request.headers['Origin'];
if (origin != null &&
_allowedOrigins != null &&
!_allowedOrigins!.contains(origin.toLowerCase())) {
return _forbidden('invalid origin "$origin".');
}
final protocol = _chooseProtocol(request);
request.hijack((channel) {
final sink = utf8.encoder.startChunkedConversion(channel.sink)
..add('HTTP/1.1 101 Switching Protocols\r\n'
'Upgrade: websocket\r\n'
'Connection: Upgrade\r\n'
'Sec-WebSocket-Accept: ${WebSocketChannel.signKey(key)}\r\n');
if (protocol != null) sink.add('Sec-WebSocket-Protocol: $protocol\r\n');
sink.add('\r\n');
_onConnection(
WebSocketChannel(channel, pingInterval: _pingInterval), protocol);
});
}