retry on HttpException (#34526)
diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart index a32f27c..0250dbd 100644 --- a/packages/flutter_tools/lib/src/base/io.dart +++ b/packages/flutter_tools/lib/src/base/io.dart
@@ -48,6 +48,7 @@ HttpClientRequest, HttpClientResponse, HttpClientResponseCompressionState, + HttpException, HttpHeaders, HttpRequest, HttpServer,
diff --git a/packages/flutter_tools/lib/src/base/net.dart b/packages/flutter_tools/lib/src/base/net.dart index 28c7194..046929d 100644 --- a/packages/flutter_tools/lib/src/base/net.dart +++ b/packages/flutter_tools/lib/src/base/net.dart
@@ -64,6 +64,9 @@ } on SocketException catch (error) { printTrace('Download error: $error'); return null; + } on HttpException catch (error) { + printTrace('Download error: $error'); + return null; } final HttpClientResponse response = await request.close(); // If we're making a HEAD request, we're only checking to see if the URL is
diff --git a/packages/flutter_tools/test/base/net_test.dart b/packages/flutter_tools/test/base/net_test.dart index fc7a29e..c38437a 100644 --- a/packages/flutter_tools/test/base/net_test.dart +++ b/packages/flutter_tools/test/base/net_test.dart
@@ -105,6 +105,32 @@ ), }); +testUsingContext('retry from HttpException', () async { + String error; + FakeAsync().run((FakeAsync time) { + fetchUrl(Uri.parse('http://example.invalid/')).then((List<int> value) { + error = 'test completed unexpectedly'; + }, onError: (dynamic exception) { + error = 'test failed unexpectedly: $exception'; + }); + expect(testLogger.statusText, ''); + time.elapse(const Duration(milliseconds: 10000)); + expect(testLogger.statusText, + 'Download failed -- attempting retry 1 in 1 second...\n' + 'Download failed -- attempting retry 2 in 2 seconds...\n' + 'Download failed -- attempting retry 3 in 4 seconds...\n' + 'Download failed -- attempting retry 4 in 8 seconds...\n', + ); + }); + expect(testLogger.errorText, isEmpty); + expect(error, isNull); + expect(testLogger.traceText, contains('Download error: HttpException')); + }, overrides: <Type, Generator>{ + HttpClientFactory: () => () => MockHttpClientThrowing( + const io.HttpException('test exception handling'), + ), + }); + testUsingContext('max attempts', () async { String error; List<int> actualResult;