Skip to content

Commit a93c75b

Browse files
committed
Fix for URLs with percent-encoded paths
1 parent b9fc11b commit a93c75b

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

GCSMiddleware/GCSMiddleware.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ func generateSignedUrl(
2828
clientId: String,
2929
expiration: Int
3030
) -> String? {
31-
guard let parsedURL = URL(string: url) else { return nil }
32-
let path = parsedURL.path
31+
guard let components = URLComponents(string: url) else {
32+
print("ERROR: could parse URL string")
33+
return nil
34+
}
35+
let path = components.percentEncodedPath
3336
let toSign = "GET\n\n\n\(expiration)\n\(path)"
3437
if let signature = signSHA256(Data(toSign.utf8), withKey: key) {
3538
let signatureString = signature.base64EncodedString()

GCSMiddlewareTests/GCSMiddlewareTests.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ struct GCSMiddlewareTests {
2626
#expect(signedURL == expectedURL)
2727
}
2828

29+
@Test func generateSignedUrlFromPercentEncodedURLReturnsExpected() throws {
30+
let expectedURL = "https://storage.googleapis.com/foo/bar%20baz?GoogleAccessId=readonly@double.iam.gserviceaccount.com&Expires=1747270308&Signature=4BNAeHKlLZRqW0St49hf5FRszUsHQ9YvBHDSh3%2BsFxyQec%2F14nwvZR5%2FB%2FMU6199kswVu1IFFAnJADqSHwnpIvJd1yxtj8vFIM8wcaWGGtleQFVRXjQPJXi%2BUfyRNrWhhqAmmch9D%2F3aEQNEcVFejiq7d4wtgokbM2gGN3rQGEFrVMWtwXdi%2F6j%2FE3rOBuGNIgn429c%2BFg%2BoK0AHEZ2hac1QKdNqt%2Fp64zkwlicHhMjW%2FbN9ha5i6o0YLn1dKkQG1K9WZyi880TiPHpZNYd%2Fke7OhwM9nLL8zff13l7FaH7hsHxTPwTHG%2BtD4116AUKTbO6vpfLRmWWPwBAwRyJHkQ%3D%3D"
31+
let url = "https://storage.googleapis.com/foo/bar%20baz"
32+
let clientId = "readonly@double.iam.gserviceaccount.com"
33+
let expiration = 1_747_270_308
34+
let key = rsaPrivateKeyFromPemString(RSA_PRIVATE_KEY_STRING)
35+
let unwrappedKey = try #require(key, "Could not load RSA private key from PEM string")
36+
37+
let signedURL = generateSignedUrl(
38+
url,
39+
withKey: unwrappedKey,
40+
clientId: clientId,
41+
expiration: expiration,
42+
)
43+
#expect(signedURL == expectedURL)
44+
}
45+
2946
// Make sure we can parse the gcs.json file
3047
@Test func readJsonKeyStore() throws {
3148
let jsonPath = try #require(TestingResource.path(for: "gcs.json"),

0 commit comments

Comments
 (0)