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
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -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>()));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user