Start switching hijacking to use StreamChannel.
R=kevmoo@google.com
Review URL: https://codereview.chromium.org//1640323004 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a73aa30..37b00bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.6.5
+
+* `Request.hijack()` now takes a callback that accepts a single `StreamChannel`
+ argument rather than separate `Stream` and `StreamSink` arguments. The old
+ callback signature is still supported, but should be considered deprecated.
+
+* The `HijackCallback` and `OnHijackCallback` typedefs are deprecated.
+
## 0.6.4+3
* Support `http_parser` 2.0.0.
diff --git a/lib/src/request.dart b/lib/src/request.dart
index 29e897a..b4d0e03 100644
--- a/lib/src/request.dart
+++ b/lib/src/request.dart
@@ -6,17 +6,20 @@
import 'dart:convert';
import 'package:http_parser/http_parser.dart';
+import 'package:stream_channel/stream_channel.dart';
import 'hijack_exception.dart';
import 'message.dart';
import 'util.dart';
/// A callback provided by a Shelf handler that's passed to [Request.hijack].
+@Deprecated("Will be removed in shelf 0.7.0.")
typedef void HijackCallback(
Stream<List<int>> stream, StreamSink<List<int>> sink);
/// A callback provided by a Shelf adapter that's used by [Request.hijack] to
/// provide a [HijackCallback] with a socket.
+@Deprecated("Will be removed in shelf 0.7.0.")
typedef void OnHijackCallback(HijackCallback callback);
/// Represents an HTTP request to be processed by a Shelf application.
@@ -133,7 +136,8 @@
Request(String method, Uri requestedUri, {String protocolVersion,
Map<String, String> headers, String handlerPath, Uri url, body,
Encoding encoding, Map<String, Object> context,
- OnHijackCallback onHijack})
+ void onHijack(void hijack(
+ Stream<List<int>> stream, StreamSink<List<int>> sink))})
: this._(method, requestedUri,
protocolVersion: protocolVersion,
headers: headers,
@@ -226,23 +230,29 @@
///
/// Synchronously, this throws a [HijackException] that indicates to the
/// adapter that it shouldn't emit a response itself. Asynchronously,
- /// [callback] is called with a [Stream<List<int>>] and
- /// [StreamSink<List<int>>], respectively, that provide access to the
- /// underlying request socket.
+ /// [callback] is called with a [StreamChannel<List<int>>] that provides
+ /// access to the underlying request socket.
///
- /// If the sink is closed, the stream will be closed as well. The stream and
- /// sink may be the same object, as in the case of a `dart:io` `Socket`
- /// object.
+ /// For backwards compatibility, if the callback takes two arguments, it will
+ /// be passed a `Stream<List<int>>` and a `StreamSink<List<int>>` separately,
+ /// but this behavior is deprecated.
///
/// This may only be called when using a Shelf adapter that supports
/// hijacking, such as the `dart:io` adapter. In addition, a given request may
/// only be hijacked once. [canHijack] can be used to detect whether this
/// request can be hijacked.
- void hijack(HijackCallback callback) {
+ void hijack(Function callback) {
if (_onHijack == null) {
throw new StateError("This request can't be hijacked.");
}
+ if (callback is ZoneUnaryCallback) {
+ var oldCallback = callback;
+ callback = (stream, sink) {
+ oldCallback(new StreamChannel<List<int>>(stream, sink));
+ };
+ }
+
_onHijack.run(callback);
throw const HijackException();
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 24d7d99..231c612 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: shelf
-version: 0.6.4+3
+version: 0.6.5-dev
author: Dart Team <misc@dartlang.org>
description: Web Server Middleware for Dart
homepage: https://github.com/dart-lang/shelf
@@ -10,7 +10,12 @@
http_parser: '>=1.0.0 <3.0.0'
path: '^1.0.0'
stack_trace: '^1.0.0'
+ stream_channel: '^1.0.0'
dev_dependencies:
http: '>=0.9.2 <0.12.0'
scheduled_test: '^0.12.0'
test: '^0.12.0'
+
+dependency_overrides:
+ stream_channel:
+ git: git://github.com/dart-lang/stream_channel
diff --git a/test/hijack_test.dart b/test/hijack_test.dart
index 82b33eb..6b6c233 100644
--- a/test/hijack_test.dart
+++ b/test/hijack_test.dart
@@ -11,7 +11,7 @@
void main() {
test('hijacking a non-hijackable request throws a StateError', () {
- expect(() => new Request('GET', LOCALHOST_URI).hijack((_, __) => null),
+ expect(() => new Request('GET', LOCALHOST_URI).hijack((_) => null),
throwsStateError);
});
@@ -29,10 +29,10 @@
callback(streamController.stream, sinkController);
}));
- expect(() => request.hijack(expectAsync((stream, sink) {
- expect(stream.first, completion(equals([1, 2, 3])));
- sink.add([4, 5, 6]);
- sink.close();
+ expect(() => request.hijack(expectAsync((channel) {
+ expect(channel.stream.first, completion(equals([1, 2, 3])));
+ channel.sink.add([4, 5, 6]);
+ channel.sink.close();
})), throwsA(new isInstanceOf<HijackException>()));
});
@@ -41,17 +41,17 @@
var request = new Request('GET', LOCALHOST_URI,
onHijack: expectAsync((_) => null, count: 1));
- expect(() => request.hijack((_, __) => null),
+ expect(() => request.hijack((_) => null),
throwsA(new isInstanceOf<HijackException>()));
- expect(() => request.hijack((_, __) => null), throwsStateError);
+ expect(() => request.hijack((_) => null), throwsStateError);
});
group('calling change', () {
test('hijacking a non-hijackable request throws a StateError', () {
var request = new Request('GET', LOCALHOST_URI);
var newRequest = request.change();
- expect(() => newRequest.hijack((_, __) => null), throwsStateError);
+ expect(() => newRequest.hijack((_) => null), throwsStateError);
});
test('hijacking a hijackable request throws a HijackException and calls '
@@ -70,10 +70,10 @@
var newRequest = request.change();
- expect(() => newRequest.hijack(expectAsync((stream, sink) {
- expect(stream.first, completion(equals([1, 2, 3])));
- sink.add([4, 5, 6]);
- sink.close();
+ expect(() => newRequest.hijack(expectAsync((channel) {
+ expect(channel.stream.first, completion(equals([1, 2, 3])));
+ channel.sink.add([4, 5, 6]);
+ channel.sink.close();
})), throwsA(new isInstanceOf<HijackException>()));
});
@@ -85,10 +85,10 @@
var newRequest = request.change();
- expect(() => newRequest.hijack((_, __) => null),
+ expect(() => newRequest.hijack((_) => null),
throwsA(new isInstanceOf<HijackException>()));
- expect(() => request.hijack((_, __) => null), throwsStateError);
+ expect(() => request.hijack((_) => null), throwsStateError);
});
});
}