Using custom exception class for network loading error (#35335)
Using custom exception class for network loading error
diff --git a/packages/flutter/lib/src/painting/_network_image_io.dart b/packages/flutter/lib/src/painting/_network_image_io.dart
index 5f9129b..2b2c4a7 100644
--- a/packages/flutter/lib/src/painting/_network_image_io.dart
+++ b/packages/flutter/lib/src/painting/_network_image_io.dart
@@ -87,7 +87,7 @@
});
final HttpClientResponse response = await request.close();
if (response.statusCode != HttpStatus.ok)
- throw Exception('HTTP request failed, statusCode: ${response?.statusCode}, $resolved');
+ throw image_provider.NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
final Uint8List bytes = await consolidateHttpClientResponseBytes(
response,
diff --git a/packages/flutter/lib/src/painting/image_provider.dart b/packages/flutter/lib/src/painting/image_provider.dart
index 4f16b93..a08e4c9 100644
--- a/packages/flutter/lib/src/painting/image_provider.dart
+++ b/packages/flutter/lib/src/painting/image_provider.dart
@@ -780,3 +780,25 @@
);
}
}
+
+/// The exception thrown when the HTTP request to load a network image fails.
+class NetworkImageLoadException implements Exception {
+ /// Creates a [NetworkImageLoadException] with the specified http status
+ /// [code] and the [uri]
+ NetworkImageLoadException({@required this.statusCode, @required this.uri})
+ : assert(uri != null),
+ assert(statusCode != null),
+ _message = 'HTTP request failed, statusCode: $statusCode, $uri';
+
+ /// The HTTP status code from the server.
+ final int statusCode;
+
+ /// A human-readable error message.
+ final String _message;
+
+ /// Resolved URI of the requested image.
+ final Uri uri;
+
+ @override
+ String toString() => _message;
+}
diff --git a/packages/flutter/test/painting/image_provider_test.dart b/packages/flutter/test/painting/image_provider_test.dart
index 656edfc..e485eec 100644
--- a/packages/flutter/test/painting/image_provider_test.dart
+++ b/packages/flutter/test/painting/image_provider_test.dart
@@ -11,6 +11,7 @@
import 'package:flutter/painting.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
+import 'package:test_api/test_api.dart' show TypeMatcher;
import '../rendering/rendering_tester.dart';
import 'image_data.dart';
@@ -154,6 +155,32 @@
debugNetworkImageHttpClientProvider = null;
});
+ test('Expect thrown exception with statusCode', () async {
+ final int errorStatusCode = HttpStatus.notFound;
+ const String requestUrl = 'foo-url';
+
+ final MockHttpClientRequest request = MockHttpClientRequest();
+ final MockHttpClientResponse response = MockHttpClientResponse();
+ when(httpClient.getUrl(any)).thenAnswer((_) => Future<HttpClientRequest>.value(request));
+ when(request.close()).thenAnswer((_) => Future<HttpClientResponse>.value(response));
+ when(response.statusCode).thenReturn(errorStatusCode);
+
+ final Completer<dynamic> caughtError = Completer<dynamic>();
+
+ final ImageProvider imageProvider = NetworkImage(nonconst(requestUrl));
+ final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
+ result.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {
+ }, onError: (dynamic error, StackTrace stackTrace) {
+ caughtError.complete(error);
+ }));
+
+ final dynamic err = await caughtError.future;
+ expect(err, const TypeMatcher<NetworkImageLoadException>()
+ .having((NetworkImageLoadException e) => e.statusCode, 'statusCode', errorStatusCode)
+ .having((NetworkImageLoadException e) => e.uri, 'uri', Uri.base.resolve(requestUrl))
+ );
+ });
+
test('Disallows null urls', () {
expect(() {
NetworkImage(nonconst(null));