From a772d4d314271e69eaa3ccb94c08fdc05de29d34 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 17 Jun 2019 10:48:01 -0700 Subject: [PATCH] retry on HttpException (#34526) --- packages/flutter_tools/lib/src/base/io.dart | 1 + packages/flutter_tools/lib/src/base/net.dart | 3 +++ .../flutter_tools/test/base/net_test.dart | 26 +++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart index a32f27c766..0250dbd997 100644 --- a/packages/flutter_tools/lib/src/base/io.dart +++ b/packages/flutter_tools/lib/src/base/io.dart @@ -48,6 +48,7 @@ export 'dart:io' 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 28c7194ff9..046929d0bb 100644 --- a/packages/flutter_tools/lib/src/base/net.dart +++ b/packages/flutter_tools/lib/src/base/net.dart @@ -64,6 +64,9 @@ Future> _attempt(Uri url, { bool onlyHeaders = false }) async { } 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 fc7a29e4b2..c38437ad6b 100644 --- a/packages/flutter_tools/test/base/net_test.dart +++ b/packages/flutter_tools/test/base/net_test.dart @@ -105,6 +105,32 @@ void main() { ), }); +testUsingContext('retry from HttpException', () async { + String error; + FakeAsync().run((FakeAsync time) { + fetchUrl(Uri.parse('http://example.invalid/')).then((List 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: { + HttpClientFactory: () => () => MockHttpClientThrowing( + const io.HttpException('test exception handling'), + ), + }); + testUsingContext('max attempts', () async { String error; List actualResult;