Remove support for requests not made through dart:io Sockets (#423)
diff --git a/pkgs/shelf_web_socket/CHANGELOG.md b/pkgs/shelf_web_socket/CHANGELOG.md
index d3596ce..5984e06 100644
--- a/pkgs/shelf_web_socket/CHANGELOG.md
+++ b/pkgs/shelf_web_socket/CHANGELOG.md
@@ -1,6 +1,8 @@
-## 1.0.5-wip
+## 2.0.0-wip
* Require Dart `^3.0.0`.
+* **BREAKING:**: Remove support for hijacking WebSocket requests that are not
+ being transported using `dart:io` `Socket`s.
## 1.0.4
diff --git a/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart b/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
index 1728765..a41ed69 100644
--- a/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
+++ b/pkgs/shelf_web_socket/lib/src/web_socket_handler.dart
@@ -3,8 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
+import 'dart:io';
import 'package:shelf/shelf.dart';
+import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
/// A class that exposes a handler for upgrading WebSocket requests.
@@ -78,9 +80,16 @@
if (protocol != null) sink.add('Sec-WebSocket-Protocol: $protocol\r\n');
sink.add('\r\n');
+ if (channel.sink is! Socket) {
+ throw ArgumentError('channel.sink must be a dart:io `Socket`.');
+ }
+
+ final webSocket = WebSocket.fromUpgradedSocket(channel.sink as Socket,
+ protocol: protocol, serverSide: true)
+ ..pingInterval = _pingInterval;
+
// ignore: avoid_dynamic_calls
- _onConnection(
- WebSocketChannel(channel, pingInterval: _pingInterval), protocol);
+ _onConnection(IOWebSocketChannel(webSocket), protocol);
});
}
diff --git a/pkgs/shelf_web_socket/pubspec.yaml b/pkgs/shelf_web_socket/pubspec.yaml
index 9c3fd94..2a8f846 100644
--- a/pkgs/shelf_web_socket/pubspec.yaml
+++ b/pkgs/shelf_web_socket/pubspec.yaml
@@ -1,5 +1,5 @@
name: shelf_web_socket
-version: 1.0.5-wip
+version: 2.0.0-wip
description: >
A shelf handler that wires up a listener for every connection.
repository: https://github.com/dart-lang/shelf/tree/master/pkgs/shelf_web_socket
@@ -20,3 +20,8 @@
dart_flutter_team_lints: ^2.0.0
http: '>=0.13.0 <2.0.0'
test: ^1.16.0
+
+# Remove this when a version of `package:test` is released that is compatible
+# with self_web_socket 2.x
+dependency_overrides:
+ test: 1.25.2
diff --git a/pkgs/shelf_web_socket/test/web_socket_test.dart b/pkgs/shelf_web_socket/test/web_socket_test.dart
index b519592..eb8e00b 100644
--- a/pkgs/shelf_web_socket/test/web_socket_test.dart
+++ b/pkgs/shelf_web_socket/test/web_socket_test.dart
@@ -5,8 +5,10 @@
import 'dart:io';
import 'package:http/http.dart' as http;
+import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
+import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
@@ -103,6 +105,32 @@
}
});
+ test('cannot hijack non-Socket StreamChannel', () async {
+ final handler =
+ webSocketHandler((WebSocketChannel webSocket, String? protocol) {
+ expect(protocol, isNull);
+ webSocket.sink.close();
+ });
+
+ expect(
+ () => handler(Request('GET', Uri.parse('ws://example.com/'),
+ protocolVersion: '1.1',
+ headers: {
+ 'Host': 'example.com',
+ 'Upgrade': 'websocket',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key': 'x3JJHMbDL1EzLkh9GBhXDw==',
+ 'Sec-WebSocket-Version': '13',
+ 'Origin': 'http://example.com',
+ }, onHijack: (fn) {
+ // `.foreign` is not a Socket so hijacking the request should
+ // fail.
+ expect(() => fn(StreamChannelController<List<int>>().foreign),
+ throwsArgumentError);
+ })),
+ throwsA(isA<HijackException>()));
+ });
+
group('with a set of allowed origins', () {
late HttpServer server;
late Uri url;