Unverified Commit 85cb38e7 authored by Dan Field's avatar Dan Field Committed by GitHub

Fix consolidate HTTP response and add test (#17082)

* Fix consolidate response and add test

* Update AUTHORS

* ignore content-length

* fix formatting/update comment

* more commas

* Fix consolidate response and add test

* Update AUTHORS

* ignore content-length

* fix formatting/update comment

* more commas

* remove extra newline
parent 62b7aee9
......@@ -21,3 +21,4 @@ Yusuke Konishi <yahpeycoy0403@gmail.com>
Fredrik Simón <fredrik@fsimon.net>
Ali Bitek <alibitek@protonmail.ch>
Tetsuhiro Ueda <najeira@gmail.com>
Dan Field <dfield@gmail.com>
......@@ -10,39 +10,24 @@ import 'dart:typed_data';
///
/// The future returned will forward all errors emitted by [response].
Future<Uint8List> consolidateHttpClientResponseBytes(HttpClientResponse response) {
// dart:io guarantees that [contentLength] is -1 if the the header is missing or
// invalid. This could still happen if a mocked response object does not fully
// implement the interface.
assert(response.contentLength != null);
// response.contentLength is not trustworthy when GZIP is involved
// or other cases where an intermediate transformer has been applied
// to the stream.
final Completer<Uint8List> completer = new Completer<Uint8List>.sync();
if (response.contentLength == -1) {
final List<List<int>> chunks = <List<int>>[];
int contentLength = 0;
response.listen((List<int> chunk) {
chunks.add(chunk);
contentLength += chunk.length;
}, onDone: () {
final Uint8List bytes = new Uint8List(contentLength);
int offset = 0;
for (List<int> chunk in chunks) {
bytes.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
}
completer.complete(bytes);
}, onError: completer.completeError, cancelOnError: true);
} else {
// If the response has a content length, then allocate a buffer of the correct size.
final Uint8List bytes = new Uint8List(response.contentLength);
final List<List<int>> chunks = <List<int>>[];
int contentLength = 0;
response.listen((List<int> chunk) {
chunks.add(chunk);
contentLength += chunk.length;
}, onDone: () {
final Uint8List bytes = new Uint8List(contentLength);
int offset = 0;
response.listen((List<int> chunk) {
for (List<int> chunk in chunks) {
bytes.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
},
onError: completer.completeError,
onDone: () {
completer.complete(bytes);
},
cancelOnError: true);
}
}
completer.complete(bytes);
}, onError: completer.completeError, cancelOnError: true);
return completer.future;
}
......@@ -24,21 +24,40 @@ void main() {
final void Function() onDone = invocation.namedArguments[#onDone];
final bool cancelOnError = invocation.namedArguments[#cancelOnError];
return new Stream<List<int>>.fromIterable(<List<int>>[chunkOne, chunkTwo])
.listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError);
return new Stream<List<int>>.fromIterable(
<List<int>>[chunkOne, chunkTwo]).listen(
onData,
onDone: onDone,
onError: onError,
cancelOnError: cancelOnError,
);
});
});
test('Converts an HttpClientResponse with contentLength to bytes', () async {
when(response.contentLength).thenReturn(chunkOne.length + chunkTwo.length);
final List<int> bytes = await consolidateHttpClientResponseBytes(response);
test('Converts an HttpClientResponse with contentLength to bytes',
() async {
when(response.contentLength)
.thenReturn(chunkOne.length + chunkTwo.length);
final List<int> bytes =
await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
});
test('Converts an HttpClientResponse without contentLength to bytes', () async {
test('Converts a compressed HttpClientResponse with contentLength to bytes',
() async {
when(response.contentLength).thenReturn(chunkOne.length);
final List<int> bytes =
await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
});
test('Converts an HttpClientResponse without contentLength to bytes',
() async {
when(response.contentLength).thenReturn(-1);
final List<int> bytes = await consolidateHttpClientResponseBytes(response);
final List<int> bytes =
await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
});
......@@ -55,12 +74,19 @@ void main() {
final void Function() onDone = invocation.namedArguments[#onDone];
final bool cancelOnError = invocation.namedArguments[#cancelOnError];
return new Stream<List<int>>.fromFuture(new Future<List<int>>.error(new Exception('Test Error')))
.listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError);
return new Stream<List<int>>.fromFuture(
new Future<List<int>>.error(new Exception('Test Error')))
.listen(
onData,
onDone: onDone,
onError: onError,
cancelOnError: cancelOnError,
);
});
when(response.contentLength).thenReturn(-1);
expect(consolidateHttpClientResponseBytes(response), throwsA(const isInstanceOf<Exception>()));
expect(consolidateHttpClientResponseBytes(response),
throwsA(const isInstanceOf<Exception>()));
});
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment