Fix all strong mode warnings.
R=rnystrom@google.com
Review URL: https://codereview.chromium.org//1913383002 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 087107d..e609b67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.11.3+4
+
+* Fix all strong mode warnings.
+
## 0.11.3+3
* Support `http_parser` 2.0.0.
diff --git a/lib/browser_client.dart b/lib/browser_client.dart
index d1179dc..883b2b1 100644
--- a/lib/browser_client.dart
+++ b/lib/browser_client.dart
@@ -4,6 +4,7 @@
import 'dart:async';
import 'dart:html';
+import 'dart:typed_data';
import 'package:stack_trace/stack_trace.dart';
@@ -42,53 +43,63 @@
bool withCredentials = false;
/// Sends an HTTP request and asynchronously returns the response.
- Future<StreamedResponse> send(BaseRequest request) {
- return request.finalize().toBytes().then((bytes) {
- var xhr = new HttpRequest();
- _xhrs.add(xhr);
- xhr.open(request.method, request.url.toString(), async: true);
- xhr.responseType = 'blob';
- xhr.withCredentials = withCredentials;
- request.headers.forEach(xhr.setRequestHeader);
+ Future<StreamedResponse> send(BaseRequest request) async {
+ var bytes = await request.finalize().toBytes();
+ var xhr = new HttpRequest();
+ _xhrs.add(xhr);
+ _openHttpRequest(xhr, request.method, request.url.toString(), asynch: true);
+ xhr.responseType = 'blob';
+ xhr.withCredentials = withCredentials;
+ request.headers.forEach(xhr.setRequestHeader);
- var completer = new Completer();
- xhr.onLoad.first.then((_) {
- // TODO(nweiz): Set the response type to "arraybuffer" when issue 18542
- // is fixed.
- var blob = xhr.response == null ? new Blob([]) : xhr.response;
- var reader = new FileReader();
+ var completer = new Completer<StreamedResponse>();
+ xhr.onLoad.first.then((_) {
+ // TODO(nweiz): Set the response type to "arraybuffer" when issue 18542
+ // is fixed.
+ var blob = xhr.response == null ? new Blob([]) : xhr.response;
+ var reader = new FileReader();
- reader.onLoad.first.then((_) {
- var body = reader.result;
- completer.complete(new StreamedResponse(
- new ByteStream.fromBytes(body),
- xhr.status,
- contentLength: body.length,
- request: request,
- headers: xhr.responseHeaders,
- reasonPhrase: xhr.statusText));
- });
-
- reader.onError.first.then((error) {
- completer.completeError(
- new ClientException(error.toString(), request.url),
- new Chain.current());
- });
-
- reader.readAsArrayBuffer(blob);
+ reader.onLoad.first.then((_) {
+ var body = reader.result as Uint8List;
+ completer.complete(new StreamedResponse(
+ new ByteStream.fromBytes(body),
+ xhr.status,
+ contentLength: body.length,
+ request: request,
+ headers: xhr.responseHeaders,
+ reasonPhrase: xhr.statusText));
});
- xhr.onError.first.then((_) {
- // Unfortunately, the underlying XMLHttpRequest API doesn't expose any
- // specific information about the error itself.
+ reader.onError.first.then((error) {
completer.completeError(
- new ClientException("XMLHttpRequest error.", request.url),
+ new ClientException(error.toString(), request.url),
new Chain.current());
});
- xhr.send(bytes);
- return completer.future.whenComplete(() => _xhrs.remove(xhr));
+ reader.readAsArrayBuffer(blob);
});
+
+ xhr.onError.first.then((_) {
+ // Unfortunately, the underlying XMLHttpRequest API doesn't expose any
+ // specific information about the error itself.
+ completer.completeError(
+ new ClientException("XMLHttpRequest error.", request.url),
+ new Chain.current());
+ });
+
+ xhr.send(bytes);
+
+ try {
+ return await completer.future;
+ } finally {
+ _xhrs.remove(xhr);
+ }
+ }
+
+ // TODO(nweiz): Remove this when sdk#24637 is fixed.
+ void _openHttpRequest(HttpRequest request, String method, String url,
+ {bool asynch, String user, String password}) {
+ request.open(method, url, async: asynch, user: user, password: password);
}
/// Closes the client.
diff --git a/lib/src/base_client.dart b/lib/src/base_client.dart
index cd5945e..7b3fbfa 100644
--- a/lib/src/base_client.dart
+++ b/lib/src/base_client.dart
@@ -6,6 +6,8 @@
import 'dart:convert';
import 'dart:typed_data';
+import 'package:collection/collection.dart';
+
import 'base_request.dart';
import 'client.dart';
import 'exception.dart';
@@ -158,9 +160,9 @@
if (body is String) {
request.body = body;
} else if (body is List) {
- request.bodyBytes = body;
+ request.bodyBytes = DelegatingList.typed(body);
} else if (body is Map) {
- request.bodyFields = body;
+ request.bodyFields = DelegatingMap.typed(body);
} else {
throw new ArgumentError('Invalid request body "$body".');
}
diff --git a/lib/src/base_request.dart b/lib/src/base_request.dart
index a9318cc..b11ef05 100644
--- a/lib/src/base_request.dart
+++ b/lib/src/base_request.dart
@@ -109,9 +109,11 @@
/// the request is complete. If you're planning on making multiple requests to
/// the same server, you should use a single [Client] for all of those
/// requests.
- Future<StreamedResponse> send() {
+ Future<StreamedResponse> send() async {
var client = new Client();
- return client.send(this).then((response) {
+
+ try {
+ var response = await client.send(this);
var stream = onDone(response.stream, client.close);
return new StreamedResponse(
new ByteStream(stream),
@@ -122,10 +124,10 @@
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase);
- }).catchError((e) {
+ } catch (_) {
client.close();
- throw e;
- });
+ rethrow;
+ }
}
// Throws an error if this request has been finalized.
diff --git a/lib/src/byte_stream.dart b/lib/src/byte_stream.dart
index 2ce4deb..a9d47b0 100644
--- a/lib/src/byte_stream.dart
+++ b/lib/src/byte_stream.dart
@@ -6,8 +6,6 @@
import 'dart:convert';
import 'dart:typed_data';
-import 'utils.dart';
-
/// A stream of chunks of bytes representing a single piece of data.
class ByteStream extends StreamView<List<int>> {
ByteStream(Stream<List<int>> stream)
@@ -16,11 +14,11 @@
/// Returns a single-subscription byte stream that will emit the given bytes
/// in a single chunk.
factory ByteStream.fromBytes(List<int> bytes) =>
- new ByteStream(streamFromIterable([bytes]));
+ new ByteStream(new Stream.fromIterable([bytes]));
/// Collects the data of this stream in a [Uint8List].
Future<Uint8List> toBytes() {
- var completer = new Completer();
+ var completer = new Completer<Uint8List>();
var sink = new ByteConversionSink.withCallback((bytes) =>
completer.complete(new Uint8List.fromList(bytes)));
listen(sink.add, onError: completer.completeError, onDone: sink.close,
@@ -34,5 +32,5 @@
encoding.decodeStream(this);
Stream<String> toStringStream([Encoding encoding=UTF8]) =>
- transform(encoding.decoder);
+ encoding.decoder.bind(this);
}
diff --git a/lib/src/io_client.dart b/lib/src/io_client.dart
index 3f7bfc9..7387a30 100644
--- a/lib/src/io_client.dart
+++ b/lib/src/io_client.dart
@@ -4,6 +4,8 @@
import 'dart:async';
+import 'package:async/async.dart';
+
import 'base_client.dart';
import 'base_request.dart';
import 'exception.dart';
@@ -34,45 +36,47 @@
}
/// Sends an HTTP request and asynchronously returns the response.
- Future<StreamedResponse> send(BaseRequest request) {
+ Future<StreamedResponse> send(BaseRequest request) async {
var stream = request.finalize();
- return _inner.openUrl(request.method, request.url)
- .then((ioRequest) {
- var contentLength = request.contentLength == null ?
- -1 : request.contentLength;
+ try {
+ var ioRequest = await _inner.openUrl(request.method, request.url);
+
ioRequest
..followRedirects = request.followRedirects
..maxRedirects = request.maxRedirects
- ..contentLength = contentLength
+ ..contentLength = request.contentLength == null
+ ? -1
+ : request.contentLength
..persistentConnection = request.persistentConnection;
request.headers.forEach((name, value) {
ioRequest.headers.set(name, value);
});
- return stream.pipe(ioRequest);
- }).then((response) {
- var headers = {};
+
+ var response = await stream.pipe(
+ DelegatingStreamConsumer.typed(ioRequest));
+ var headers = <String, String>{};
response.headers.forEach((key, values) {
headers[key] = values.join(',');
});
- var contentLength = response.contentLength == -1 ?
- null : response.contentLength;
return new StreamedResponse(
- response.handleError((error) =>
+ DelegatingStream.typed/*<List<int>>*/(response).handleError((error) =>
throw new ClientException(error.message, error.uri),
test: (error) => io.isHttpException(error)),
response.statusCode,
- contentLength: contentLength,
+ contentLength: response.contentLength == -1
+ ? null
+ : response.contentLength,
request: request,
headers: headers,
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase);
- }).catchError((error) {
- if (!io.isHttpException(error)) throw error;
+ } catch (error) {
+ if (!io.isHttpException(error)) rethrow;
throw new ClientException(error.message, error.uri);
- });
+ }
}
/// Closes the client. This terminates all active connections. If a client
diff --git a/lib/src/multipart_request.dart b/lib/src/multipart_request.dart
index c799d70..f589eaa 100644
--- a/lib/src/multipart_request.dart
+++ b/lib/src/multipart_request.dart
@@ -47,9 +47,9 @@
/// Creates a new [MultipartRequest].
MultipartRequest(String method, Uri url)
- : super(method, url),
- fields = {},
- _files = <MultipartFile>[];
+ : fields = {},
+ _files = <MultipartFile>[],
+ super(method, url);
/// The list of files to upload for this request.
List<MultipartFile> get files => _files;
diff --git a/lib/src/request.dart b/lib/src/request.dart
index fe05d7d..67b664c 100644
--- a/lib/src/request.dart
+++ b/lib/src/request.dart
@@ -113,7 +113,7 @@
'content-type "application/x-www-form-urlencoded".');
}
- return queryToMap(body, encoding: encoding);
+ return Uri.splitQueryString(body, encoding: encoding);
}
set bodyFields(Map<String, String> fields) {
@@ -130,9 +130,9 @@
/// Creates a new HTTP request.
Request(String method, Uri url)
- : super(method, url),
- _defaultEncoding = UTF8,
- _bodyBytes = new Uint8List(0);
+ : _defaultEncoding = UTF8,
+ _bodyBytes = new Uint8List(0),
+ super(method, url);
/// Freezes all mutable fields and returns a single-subscription [ByteStream]
/// containing the request body.
diff --git a/lib/src/streamed_request.dart b/lib/src/streamed_request.dart
index e52f240..6a020bd 100644
--- a/lib/src/streamed_request.dart
+++ b/lib/src/streamed_request.dart
@@ -28,8 +28,8 @@
/// Creates a new streaming request.
StreamedRequest(String method, Uri url)
- : super(method, url),
- _controller = new StreamController<List<int>>(sync: true);
+ : _controller = new StreamController<List<int>>(sync: true),
+ super(method, url);
/// Freezes all mutable fields other than [stream] and returns a
/// single-subscription [ByteStream] that emits the data being written to
diff --git a/lib/src/streamed_response.dart b/lib/src/streamed_response.dart
index 6f20efc..69d8356 100644
--- a/lib/src/streamed_response.dart
+++ b/lib/src/streamed_response.dart
@@ -27,13 +27,13 @@
bool isRedirect: false,
bool persistentConnection: true,
String reasonPhrase})
- : super(
- statusCode,
- contentLength: contentLength,
- request: request,
- headers: headers,
- isRedirect: isRedirect,
- persistentConnection: persistentConnection,
- reasonPhrase: reasonPhrase),
- this.stream = toByteStream(stream);
+ : this.stream = toByteStream(stream),
+ super(
+ statusCode,
+ contentLength: contentLength,
+ request: request,
+ headers: headers,
+ isRedirect: isRedirect,
+ persistentConnection: persistentConnection,
+ reasonPhrase: reasonPhrase);
}
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 195bbc0..a0f5e36 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -8,24 +8,6 @@
import 'byte_stream.dart';
-/// Converts a URL query string (or `application/x-www-form-urlencoded` body)
-/// into a [Map] from parameter names to values.
-///
-/// queryToMap("foo=bar&baz=bang&qux");
-/// //=> {"foo": "bar", "baz": "bang", "qux": ""}
-Map<String, String> queryToMap(String queryList, {Encoding encoding}) {
- var map = {};
- for (var pair in queryList.split("&")) {
- var split = split1(pair, "=");
- if (split.isEmpty) continue;
- var key = Uri.decodeQueryComponent(split[0], encoding: encoding);
- var value = Uri.decodeQueryComponent(split.length > 1 ? split[1] : "",
- encoding: encoding);
- map[key] = value;
- }
- return map;
-}
-
/// Converts a [Map] from parameter names to values to a URL query string.
///
/// mapToQuery({"foo": "bar", "baz": "bang"});
@@ -104,11 +86,11 @@
/// Calls [onDone] once [stream] (a single-subscription [Stream]) is finished.
/// The return value, also a single-subscription [Stream] should be used in
/// place of [stream] after calling this method.
-Stream onDone(Stream stream, void onDone()) {
- var pair = tee(stream);
- pair.first.listen((_) {}, onError: (_) {}, onDone: onDone);
- return pair.last;
-}
+Stream/*<T>*/ onDone/*<T>*/(Stream/*<T>*/ stream, void onDone()) =>
+ stream.transform(new StreamTransformer.fromHandlers(handleDone: (sink) {
+ sink.close();
+ onDone();
+ }));
// TODO(nweiz): remove this when issue 7786 is fixed.
/// Pipes all data and errors from [stream] into [sink]. When [stream] is done,
@@ -138,38 +120,6 @@
/// Returns a [Future] that asynchronously completes to `null`.
Future get async => new Future.value();
-/// Returns a closed [Stream] with no elements.
-Stream get emptyStream => streamFromIterable([]);
-
-/// Creates a single-subscription stream that emits the items in [iter] and then
-/// ends.
-Stream streamFromIterable(Iterable iter) {
- var controller = new StreamController(sync: true);
- iter.forEach(controller.add);
- controller.close();
- return controller.stream;
-}
-
-// TODO(nweiz): remove this when issue 7787 is fixed.
-/// Creates two single-subscription [Stream]s that each emit all values and
-/// errors from [stream]. This is useful if [stream] is single-subscription but
-/// multiple subscribers are necessary.
-Pair<Stream, Stream> tee(Stream stream) {
- var controller1 = new StreamController(sync: true);
- var controller2 = new StreamController(sync: true);
- stream.listen((value) {
- controller1.add(value);
- controller2.add(value);
- }, onError: (error, [StackTrace stackTrace]) {
- controller1.addError(error, stackTrace);
- controller2.addError(error, stackTrace);
- }, onDone: () {
- controller1.close();
- controller2.close();
- });
- return new Pair<Stream, Stream>(controller1.stream, controller2.stream);
-}
-
/// A pair of values.
class Pair<E, F> {
E first;
diff --git a/pubspec.yaml b/pubspec.yaml
index f2ba38e..1c59d5e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,9 +1,11 @@
name: http
-version: 0.11.3+3
+version: 0.11.3+4
author: "Dart Team <misc@dartlang.org>"
homepage: https://github.com/dart-lang/http
description: A composable, Future-based API for making HTTP requests.
dependencies:
+ async: "^1.10.0"
+ collection: "^1.5.0"
http_parser: ">=0.0.1 <3.0.0"
path: ">=0.9.0 <2.0.0"
stack_trace: ">=0.9.1 <2.0.0"