Unverified Commit 8163c0ae authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Re-apply compressionState changes. (#34341)

This re-applies the changes that were made in #33697 and #33729,
but which were reverted in #33792 and #33790, respectively due to
the Dart SDK not having received the update within Google yet.
The SDK has now rolled, so these changes can be re-applied.

https://github.com/flutter/flutter/issues/32374
https://github.com/flutter/flutter/issues/33791
parent 25c84001
...@@ -43,10 +43,8 @@ typedef BytesReceivedCallback = void Function(int cumulative, int total); ...@@ -43,10 +43,8 @@ typedef BytesReceivedCallback = void Function(int cumulative, int total);
/// bytes from this method (assuming the response is sending compressed bytes), /// bytes from this method (assuming the response is sending compressed bytes),
/// set both [HttpClient.autoUncompress] to false and the `autoUncompress` /// set both [HttpClient.autoUncompress] to false and the `autoUncompress`
/// parameter to false. /// parameter to false.
// TODO(tvolkert): Remove the [client] param once https://github.com/dart-lang/sdk/issues/36971 is fixed.
Future<Uint8List> consolidateHttpClientResponseBytes( Future<Uint8List> consolidateHttpClientResponseBytes(
HttpClientResponse response, { HttpClientResponse response, {
HttpClient client,
bool autoUncompress = true, bool autoUncompress = true,
BytesReceivedCallback onBytesReceived, BytesReceivedCallback onBytesReceived,
}) { }) {
...@@ -58,15 +56,21 @@ Future<Uint8List> consolidateHttpClientResponseBytes( ...@@ -58,15 +56,21 @@ Future<Uint8List> consolidateHttpClientResponseBytes(
int expectedContentLength = response.contentLength; int expectedContentLength = response.contentLength;
if (expectedContentLength == -1) if (expectedContentLength == -1)
expectedContentLength = null; expectedContentLength = null;
if (response.headers?.value(HttpHeaders.contentEncodingHeader) == 'gzip') { switch (response.compressionState) {
if (client?.autoUncompress ?? true) { case HttpClientResponseCompressionState.compressed:
if (autoUncompress) {
// We need to un-compress the bytes as they come in.
sink = gzip.decoder.startChunkedConversion(output);
}
break;
case HttpClientResponseCompressionState.decompressed:
// response.contentLength will not match our bytes stream, so we declare // response.contentLength will not match our bytes stream, so we declare
// that we don't know the expected content length. // that we don't know the expected content length.
expectedContentLength = null; expectedContentLength = null;
} else if (autoUncompress) { break;
// We need to un-compress the bytes as they come in. case HttpClientResponseCompressionState.notCompressed:
sink = gzip.decoder.startChunkedConversion(output); // Fall-through.
} break;
} }
int bytesReceived = 0; int bytesReceived = 0;
......
...@@ -552,7 +552,6 @@ class NetworkImage extends ImageProvider<NetworkImage> { ...@@ -552,7 +552,6 @@ class NetworkImage extends ImageProvider<NetworkImage> {
final Uint8List bytes = await consolidateHttpClientResponseBytes( final Uint8List bytes = await consolidateHttpClientResponseBytes(
response, response,
client: _httpClient,
onBytesReceived: (int cumulative, int total) { onBytesReceived: (int cumulative, int total) {
chunkEvents.add(ImageChunkEvent( chunkEvents.add(ImageChunkEvent(
cumulativeBytesLoaded: cumulative, cumulativeBytesLoaded: cumulative,
......
...@@ -16,17 +16,11 @@ void main() { ...@@ -16,17 +16,11 @@ void main() {
group(consolidateHttpClientResponseBytes, () { group(consolidateHttpClientResponseBytes, () {
final List<int> chunkOne = <int>[0, 1, 2, 3, 4, 5]; final List<int> chunkOne = <int>[0, 1, 2, 3, 4, 5];
final List<int> chunkTwo = <int>[6, 7, 8, 9, 10]; final List<int> chunkTwo = <int>[6, 7, 8, 9, 10];
MockHttpClient client;
MockHttpClientResponse response; MockHttpClientResponse response;
MockHttpHeaders headers;
setUp(() { setUp(() {
client = MockHttpClient();
response = MockHttpClientResponse(); response = MockHttpClientResponse();
headers = MockHttpHeaders(); when(response.compressionState).thenReturn(HttpClientResponseCompressionState.notCompressed);
when(client.autoUncompress).thenReturn(true);
when(response.headers).thenReturn(headers);
when(headers.value(HttpHeaders.contentEncodingHeader)).thenReturn(null);
when(response.listen( when(response.listen(
any, any,
onDone: anyNamed('onDone'), onDone: anyNamed('onDone'),
...@@ -52,7 +46,7 @@ void main() { ...@@ -52,7 +46,7 @@ void main() {
when(response.contentLength) when(response.contentLength)
.thenReturn(chunkOne.length + chunkTwo.length); .thenReturn(chunkOne.length + chunkTwo.length);
final List<int> bytes = final List<int> bytes =
await consolidateHttpClientResponseBytes(response, client: client); await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}); });
...@@ -60,7 +54,7 @@ void main() { ...@@ -60,7 +54,7 @@ void main() {
test('Converts a compressed HttpClientResponse with contentLength to bytes', () async { test('Converts a compressed HttpClientResponse with contentLength to bytes', () async {
when(response.contentLength).thenReturn(chunkOne.length); when(response.contentLength).thenReturn(chunkOne.length);
final List<int> bytes = final List<int> bytes =
await consolidateHttpClientResponseBytes(response, client: client); await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}); });
...@@ -68,7 +62,7 @@ void main() { ...@@ -68,7 +62,7 @@ void main() {
test('Converts an HttpClientResponse without contentLength to bytes', () async { test('Converts an HttpClientResponse without contentLength to bytes', () async {
when(response.contentLength).thenReturn(-1); when(response.contentLength).thenReturn(-1);
final List<int> bytes = final List<int> bytes =
await consolidateHttpClientResponseBytes(response, client: client); await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}); });
...@@ -79,7 +73,6 @@ void main() { ...@@ -79,7 +73,6 @@ void main() {
final List<int> records = <int>[]; final List<int> records = <int>[];
await consolidateHttpClientResponseBytes( await consolidateHttpClientResponseBytes(
response, response,
client: client,
onBytesReceived: (int cumulative, int total) { onBytesReceived: (int cumulative, int total) {
records.addAll(<int>[cumulative, total]); records.addAll(<int>[cumulative, total]);
}, },
...@@ -116,7 +109,7 @@ void main() { ...@@ -116,7 +109,7 @@ void main() {
}); });
when(response.contentLength).thenReturn(-1); when(response.contentLength).thenReturn(-1);
expect(consolidateHttpClientResponseBytes(response, client: client), expect(consolidateHttpClientResponseBytes(response),
throwsA(isInstanceOf<Exception>())); throwsA(isInstanceOf<Exception>()));
}); });
...@@ -124,7 +117,6 @@ void main() { ...@@ -124,7 +117,6 @@ void main() {
when(response.contentLength).thenReturn(-1); when(response.contentLength).thenReturn(-1);
final Future<List<int>> result = consolidateHttpClientResponseBytes( final Future<List<int>> result = consolidateHttpClientResponseBytes(
response, response,
client: client,
onBytesReceived: (int cumulative, int total) { onBytesReceived: (int cumulative, int total) {
throw 'misbehaving callback'; throw 'misbehaving callback';
}, },
...@@ -139,7 +131,7 @@ void main() { ...@@ -139,7 +131,7 @@ void main() {
final List<int> gzippedChunkTwo = gzipped.sublist(gzipped.length ~/ 2); final List<int> gzippedChunkTwo = gzipped.sublist(gzipped.length ~/ 2);
setUp(() { setUp(() {
when(headers.value(HttpHeaders.contentEncodingHeader)).thenReturn('gzip'); when(response.compressionState).thenReturn(HttpClientResponseCompressionState.compressed);
when(response.listen( when(response.listen(
any, any,
onDone: anyNamed('onDone'), onDone: anyNamed('onDone'),
...@@ -161,27 +153,26 @@ void main() { ...@@ -161,27 +153,26 @@ void main() {
}); });
}); });
test('Uncompresses GZIP bytes if autoUncompress is true and response.autoUncompress is false', () async { test('Uncompresses GZIP bytes if autoUncompress is true and response.compressionState is compressed', () async {
when(client.autoUncompress).thenReturn(false); when(response.compressionState).thenReturn(HttpClientResponseCompressionState.compressed);
when(response.contentLength).thenReturn(gzipped.length); when(response.contentLength).thenReturn(gzipped.length);
final List<int> bytes = await consolidateHttpClientResponseBytes(response, client: client); final List<int> bytes = await consolidateHttpClientResponseBytes(response);
expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); expect(bytes, <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}); });
test('returns gzipped bytes if autoUncompress is false and response.autoUncompress is false', () async { test('returns gzipped bytes if autoUncompress is false and response.compressionState is compressed', () async {
when(client.autoUncompress).thenReturn(false); when(response.compressionState).thenReturn(HttpClientResponseCompressionState.compressed);
when(response.contentLength).thenReturn(gzipped.length); when(response.contentLength).thenReturn(gzipped.length);
final List<int> bytes = await consolidateHttpClientResponseBytes(response, client: client, autoUncompress: false); final List<int> bytes = await consolidateHttpClientResponseBytes(response, autoUncompress: false);
expect(bytes, gzipped); expect(bytes, gzipped);
}); });
test('Notifies onBytesReceived with gzipped numbers', () async { test('Notifies onBytesReceived with gzipped numbers', () async {
when(client.autoUncompress).thenReturn(false); when(response.compressionState).thenReturn(HttpClientResponseCompressionState.compressed);
when(response.contentLength).thenReturn(gzipped.length); when(response.contentLength).thenReturn(gzipped.length);
final List<int> records = <int>[]; final List<int> records = <int>[];
await consolidateHttpClientResponseBytes( await consolidateHttpClientResponseBytes(
response, response,
client: client,
onBytesReceived: (int cumulative, int total) { onBytesReceived: (int cumulative, int total) {
records.addAll(<int>[cumulative, total]); records.addAll(<int>[cumulative, total]);
}, },
...@@ -195,13 +186,13 @@ void main() { ...@@ -195,13 +186,13 @@ void main() {
]); ]);
}); });
test('Notifies onBytesReceived with expectedContentLength of -1 if response.autoUncompress is true', () async { test('Notifies onBytesReceived with expectedContentLength of -1 if response.compressionState is decompressed', () async {
final int syntheticTotal = (chunkOne.length + chunkTwo.length) * 2; final int syntheticTotal = (chunkOne.length + chunkTwo.length) * 2;
when(response.compressionState).thenReturn(HttpClientResponseCompressionState.decompressed);
when(response.contentLength).thenReturn(syntheticTotal); when(response.contentLength).thenReturn(syntheticTotal);
final List<int> records = <int>[]; final List<int> records = <int>[];
await consolidateHttpClientResponseBytes( await consolidateHttpClientResponseBytes(
response, response,
client: client,
onBytesReceived: (int cumulative, int total) { onBytesReceived: (int cumulative, int total) {
records.addAll(<int>[cumulative, total]); records.addAll(<int>[cumulative, total]);
}, },
...@@ -218,6 +209,4 @@ void main() { ...@@ -218,6 +209,4 @@ void main() {
}); });
} }
class MockHttpClient extends Mock implements HttpClient {}
class MockHttpClientResponse extends Mock implements HttpClientResponse {} class MockHttpClientResponse extends Mock implements HttpClientResponse {}
class MockHttpHeaders extends Mock implements HttpHeaders {}
...@@ -1770,20 +1770,10 @@ class _MockHttpResponse extends Stream<List<int>> implements HttpClientResponse ...@@ -1770,20 +1770,10 @@ class _MockHttpResponse extends Stream<List<int>> implements HttpClientResponse
@override @override
int get contentLength => -1; int get contentLength => -1;
// TODO(tvolkert): Update (flutter/flutter#33791)
/*
@override @override
HttpClientResponseCompressionState get compressionState { HttpClientResponseCompressionState get compressionState {
return HttpClientResponseCompressionState.decompressed; return HttpClientResponseCompressionState.decompressed;
} }
*/
@override
dynamic noSuchMethod(Invocation invocation) {
if (invocation.memberName == #compressionState) {
return null;
}
return super.noSuchMethod(invocation);
}
@override @override
List<Cookie> get cookies => null; List<Cookie> get cookies => null;
......
...@@ -47,8 +47,7 @@ export 'dart:io' ...@@ -47,8 +47,7 @@ export 'dart:io'
HttpClient, HttpClient,
HttpClientRequest, HttpClientRequest,
HttpClientResponse, HttpClientResponse,
// TODO(tvolkert): Uncomment (flutter/flutter#33791) HttpClientResponseCompressionState,
//HttpClientResponseCompressionState,
HttpHeaders, HttpHeaders,
HttpRequest, HttpRequest,
HttpServer, HttpServer,
......
...@@ -1295,13 +1295,10 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp ...@@ -1295,13 +1295,10 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp
@override @override
String get reasonPhrase => '<reason phrase>'; String get reasonPhrase => '<reason phrase>';
// TODO(tvolkert): Update (flutter/flutter#33791)
/*
@override @override
HttpClientResponseCompressionState get compressionState { HttpClientResponseCompressionState get compressionState {
return HttpClientResponseCompressionState.decompressed; return HttpClientResponseCompressionState.decompressed;
} }
*/
@override @override
StreamSubscription<Uint8List> listen( StreamSubscription<Uint8List> listen(
...@@ -1316,10 +1313,6 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp ...@@ -1316,10 +1313,6 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp
@override @override
dynamic noSuchMethod(Invocation invocation) { dynamic noSuchMethod(Invocation invocation) {
// TODO(tvolkert): Update (flutter/flutter#33791)
if (invocation.memberName == #compressionState) {
return null;
}
throw 'io.HttpClientResponse - $invocation'; throw 'io.HttpClientResponse - $invocation';
} }
} }
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