// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT-0 import AWSCore import TangramMap class AWSSignatureV4URLHandler: TGDefaultURLHandler { private let region: AWSRegionType private let identityPoolId: String private let credentialsProvider: AWSCredentialsProvider init(region: AWSRegionType, identityPoolId: String) { self.region = region self.identityPoolId = identityPoolId self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: region, identityPoolId: identityPoolId) super.init() } override func downloadRequestAsync(_ url: URL, completionHandler: @escaping TGDownloadCompletionHandler) -> UInt { if url.host?.contains("amazonaws.com") != true { // not an AWS URL return super.downloadRequestAsync(url, completionHandler: completionHandler) } // URL-encode spaces, etc. let keyPath = String(url.path.dropFirst()) guard let keyPathSafe = keyPath.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { print("Invalid characters in path '\(keyPath)'; unsafe to sign") return super.downloadRequestAsync(url, completionHandler: completionHandler) } // sign the URL let endpoint = AWSEndpoint(region: region, serviceName: "geo", url: url) let requestHeaders: [String: String] = ["host": endpoint!.hostName] let task = AWSSignatureV4Signer .generateQueryStringForSignatureV4( withCredentialProvider: credentialsProvider, httpMethod: .GET, expireDuration: 60, endpoint: endpoint!, keyPath: keyPathSafe, requestHeaders: requestHeaders, requestParameters: .none, signBody: true) task.waitUntilFinished() if let error = task.error as NSError? { print("Error occurred: \(error)") } if let result = task.result { // have Tangram fetch the signed URL return super.downloadRequestAsync(result as URL, completionHandler: completionHandler) } // fall back to an unsigned URL return super.downloadRequestAsync(url, completionHandler: completionHandler) } }