firebase-ios-sdk
firebase-ios-sdk copied to clipboard
FirebaseStorage - reference(forUrl: URL) Invalid url format
[REQUIRED] Step 1: Describe your environment
- Xcode version: 14 beta
- Firebase SDK version: 9.2
- Installation method: Swift Package Manager
- Firebase Component: Storage
- Target platform(s): iOS 16 beta only
[REQUIRED] Step 2: Describe the problem
After fetching the downloadUrl from a storageRef i'm receiving a correctly formatted download URL with %2F for the path parameters. When fetching the storageRef for this url using Storage.storage().reference(forUrl: URL). The returned storageRef does not properly decode the path where the object is stored in Storage i.e. gs://someapp.appspot.com/images%2FsomeImage, Expecting gs://someapp.appspot.com/images/someImage. I'm then receiving a correct permissions error as this is not the correct path to the object.
This is only occurring when testing a real device with iOS16 beta. All other versions seem to be working.
Current workaround is to use: url.removingPercentEncoding
let downloadUrl = try await storageRef.downloadURL().absoluteString
let storageRef = db.reference(forURL: url)
let data = try await storageRef.data(maxSize: 10485760)
// Correct permissions error for trying to access a object that doesn't exist - gs://someapp.appspot.com/images%2FsomeImage
let storageRef = db.reference(forURL: url.removingPercentEncoding!)
let data = try await storageRef.data(maxSize: 10485760)
// This produces expected result - gs://someapp.appspot.com/images/someImage
Thanks for pointing this out! I'm actually able to reproduce what you're seeing both on the iOS 16 simulator and a real device. I've traced it down to a change in URL.pathComponents's behaviour in iOS 16.
Example
let url = URL(string: "https://example.com/images%2Fexample.png")!
print("URL Components: \(url.pathComponents)")
- iOS 15.5:
URL Components: ["/", "images", "example.png"] - iOS 16.0 Beta 3:
URL Components: ["/", "images%2Fexample.png"]
The documentation for NSURL states:
This property contains an array containing the individual path components of the URL, each unescaped using the replacingPercentEscapes(using:) method. For example, in the URL file:///directory/directory%202/file, the path components array would be @[@"/", @"directory", @"directory 2", @"file"].
In the beta documentation, NSURL is marked as modified. The method replacingPercentEscapes(using:) is also marked as deprecated.
Unfortunately I don't have a fix quite yet since I'm not sure if the functionality change is intended or a bug in the beta. I also want to be sure that there aren't any edge cases when using removingPercentEncoding, e.g., if a file has spaces in the filename.
Cheers Andrew, thanks the detailed response. Appreciate that beta versions always have some foibles. For the time being we have a solution so for us it's not a priority. If we see any edge cases, we'll let you know!
Marking to check again with the Xcode 14 GA (or later beta) in advance of Firebase 10.
Good news! This seems to be resolved in the GM release of iOS 16.
let url = URL(string: "https://example.com/images%2Fexample%20image.png")!
print("URL Components: \(url.pathComponents)")
- iOS 16.0 Beta 3/5:
URL Components: ["/", "images%2Fexample.png"] - iOS 16.0 GM:
URL Components: ["/", "images", "example image.png"]
I tried a scenario similar to the one you posted using Storage as well:
let storage = Storage.storage()
let storageRef: StorageReference = storage.reference(forURL: "gs://someapp.appspot.com/images/Built with Firebase.png")
print("Storage Ref: \(storageRef)")
let downloadUrl = try await storageRef.downloadURL()
print("Download URL: \(downloadUrl.absoluteString)")
let downloadRef = storage.reference(forURL: downloadUrl.absoluteString)
print("Download Ref: \(downloadRef)")
let data = try await downloadRef.data(maxSize: 15000)
print("Image Size: \(data.count)")
Prints:
Storage Ref: gs://someapp.appspot.com/images/Built with Firebase.png
Download URL: https://firebasestorage.googleapis.com:443/v0/b/someapp.appspot.com/o/images%2FBuilt%20with%20Firebase.png?alt=media&token=39915302-a3ca-48a2-9ef6-c5c4187994b8
Download Ref: gs://someapp.appspot.com/images/Built with Firebase.png
Image Size: 13059
As a sanity check, I got the same results in a simulator and on a real device. Closing since this seems fixed but let us know if you see different results.