[flutter_svg] Fix SvgNetworkLoader not closing internal http client (#8126)
closes https://github.com/flutter/flutter/issues/158928
Ensures that if a Client is created in `prepareMessage` it is closed after getting the resource.
diff --git a/third_party/packages/flutter_svg/CHANGELOG.md b/third_party/packages/flutter_svg/CHANGELOG.md
index 1adca85..7f88983 100644
--- a/third_party/packages/flutter_svg/CHANGELOG.md
+++ b/third_party/packages/flutter_svg/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.0.15
+
+* Fixes `SvgNetworkLoader` not closing internally created http clients.
+
## 2.0.14
* Makes the package WASM compatible.
diff --git a/third_party/packages/flutter_svg/lib/src/loaders.dart b/third_party/packages/flutter_svg/lib/src/loaders.dart
index 2996cc1..62e3959 100644
--- a/third_party/packages/flutter_svg/lib/src/loaders.dart
+++ b/third_party/packages/flutter_svg/lib/src/loaders.dart
@@ -438,7 +438,12 @@
@override
Future<Uint8List?> prepareMessage(BuildContext? context) async {
final http.Client client = _httpClient ?? http.Client();
- return (await client.get(Uri.parse(url), headers: headers)).bodyBytes;
+ final http.Response response =
+ await client.get(Uri.parse(url), headers: headers);
+ if (_httpClient == null) {
+ client.close();
+ }
+ return response.bodyBytes;
}
@override
diff --git a/third_party/packages/flutter_svg/pubspec.yaml b/third_party/packages/flutter_svg/pubspec.yaml
index e18e014..f08db3a 100644
--- a/third_party/packages/flutter_svg/pubspec.yaml
+++ b/third_party/packages/flutter_svg/pubspec.yaml
@@ -2,7 +2,7 @@
description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files.
repository: https://github.com/flutter/packages/tree/main/third_party/packages/flutter_svg
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_svg%22
-version: 2.0.14
+version: 2.0.15
environment:
sdk: ^3.4.0
diff --git a/third_party/packages/flutter_svg/test/loaders_test.dart b/third_party/packages/flutter_svg/test/loaders_test.dart
index 591b3b0..28f5325 100644
--- a/third_party/packages/flutter_svg/test/loaders_test.dart
+++ b/third_party/packages/flutter_svg/test/loaders_test.dart
@@ -2,6 +2,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_test/flutter_test.dart';
+import 'package:http/http.dart' as http;
void main() {
setUp(() {
@@ -57,6 +58,36 @@
expect((await loader.prepareMessage(null))!.lengthInBytes, 0);
expect((await packageLoader.prepareMessage(null))!.lengthInBytes, 1);
});
+
+ test('SvgNetworkLoader closes internal client', () async {
+ final List<VerifyCloseClient> createdClients = <VerifyCloseClient>[];
+
+ await http.runWithClient(() async {
+ const SvgNetworkLoader loader = SvgNetworkLoader('');
+
+ expect(createdClients, isEmpty);
+ await loader.prepareMessage(null);
+
+ expect(createdClients, hasLength(1));
+ expect(createdClients[0].closeCalled, isTrue);
+ }, () {
+ final VerifyCloseClient client = VerifyCloseClient();
+ createdClients.add(client);
+ return client;
+ });
+ });
+
+ test("SvgNetworkLoader doesn't close passed client", () async {
+ final VerifyCloseClient client = VerifyCloseClient();
+ final SvgNetworkLoader loader = SvgNetworkLoader(
+ '',
+ httpClient: client as http.Client,
+ );
+
+ expect(client.closeCalled, isFalse);
+ await loader.prepareMessage(null);
+ expect(client.closeCalled, isFalse);
+ });
}
class TestBundle extends Fake implements AssetBundle {
@@ -96,3 +127,18 @@
return color;
}
}
+
+class VerifyCloseClient extends Fake implements http.Client {
+ bool closeCalled = false;
+
+ @override
+ Future<http.Response> get(Uri url, {Map<String, String>? headers}) async {
+ return http.Response('', 200);
+ }
+
+ @override
+ void close() {
+ assert(!closeCalled);
+ closeCalled = true;
+ }
+}