URL encode asset paths to support reserved characters in paths (#16046)
Fixes https://github.com/flutter/flutter/issues/14864
diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart
index 4227451..f6a933c 100644
--- a/packages/flutter/lib/src/services/asset_bundle.dart
+++ b/packages/flutter/lib/src/services/asset_bundle.dart
@@ -214,7 +214,7 @@
class PlatformAssetBundle extends CachingAssetBundle {
@override
Future<ByteData> load(String key) async {
- final Uint8List encoded = utf8.encoder.convert(new Uri(path: key).path);
+ final Uint8List encoded = utf8.encoder.convert(new Uri(path: Uri.encodeFull(key)).path);
final ByteData asset =
await BinaryMessages.send('flutter/assets', encoded.buffer.asByteData());
if (asset == null)
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index 03cd721..1731ceb 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -59,7 +59,7 @@
}
List<Uri> get assets {
- return _flutterDescriptor['assets']?.map(Uri.parse)?.toList() ?? const <Uri>[];
+ return _flutterDescriptor['assets']?.map(Uri.encodeFull)?.map(Uri.parse)?.toList() ?? const <Uri>[];
}
List<Font> _fonts;
diff --git a/packages/flutter_tools/test/asset_bundle_package_test.dart b/packages/flutter_tools/test/asset_bundle_package_test.dart
index ab7e2a4..baf92ea 100644
--- a/packages/flutter_tools/test/asset_bundle_package_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_package_test.dart
@@ -69,7 +69,7 @@
for (String packageName in packages) {
for (String asset in assets) {
- final String entryKey = 'packages/$packageName/$asset';
+ final String entryKey = Uri.encodeFull('packages/$packageName/$asset');
expect(bundle.entries.containsKey(entryKey), true);
expect(
utf8.decode(await bundle.entries[entryKey].contentsAsBytes()),
@@ -415,4 +415,29 @@
);
});
});
+
+ testUsingContext('Asset paths can contain URL reserved characters', () async {
+ establishFlutterRoot();
+
+ writePubspecFile('pubspec.yaml', 'test');
+ writePackagesFile('test_package:p/p/lib/');
+
+ final List<String> assets = <String>['a/foo', 'a/foo[x]'];
+ writePubspecFile(
+ 'p/p/pubspec.yaml',
+ 'test_package',
+ assets: assets,
+ );
+
+ writeAssets('p/p/', assets);
+ const String expectedAssetManifest =
+ '{"packages/test_package/a/foo":["packages/test_package/a/foo"],'
+ '"packages/test_package/a/foo%5Bx%5D":["packages/test_package/a/foo%5Bx%5D"]}';
+
+ await buildAndVerifyAssets(
+ assets,
+ <String>['test_package'],
+ expectedAssetManifest,
+ );
+ });
}