From 0f7233425597c27a84684ae405f42a84d7a35f88 Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:58:17 -0400 Subject: [PATCH 1/2] chore: Updating README [skip ci] (#3874) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28552426e4..994d2d924e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ AWS Amplify provides a declarative and easy-to-use interface across different categories of cloud operations. Our default implementation works with Amazon Web Services (AWS), but AWS Amplify is designed to be open and pluggable for any custom backend or service. -The Amplify Library for Swift is layered on the [AWS SDK for Swift](https://aws.amazon.com/sdk-for-swift/), which was released as Developer Preview last year. This allows for access to the AWS SDK for Swift for a breadth of service-centric APIs. +The Amplify Library for Swift is layered on the [AWS SDK for Swift](https://aws.amazon.com/sdk-for-swift/). This allows for access to the AWS SDK for Swift for a breadth of service-centric APIs. [**API Documentation**](https://aws-amplify.github.io/amplify-swift/docs/) From 0a499673736fc87f344954a01de3d11d96987919 Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:59:10 -0400 Subject: [PATCH 2/2] fix(Storage): Removing testable import on UploadPartInput extension (#3878) --- .../UploadPartInput+presignURL.swift | 95 +++++++++++++++++-- 1 file changed, 88 insertions(+), 7 deletions(-) diff --git a/AmplifyPlugins/Storage/Sources/AWSS3StoragePlugin/Dependency/UploadPartInput+presignURL.swift b/AmplifyPlugins/Storage/Sources/AWSS3StoragePlugin/Dependency/UploadPartInput+presignURL.swift index ae89c9359e..0350c6ca01 100644 --- a/AmplifyPlugins/Storage/Sources/AWSS3StoragePlugin/Dependency/UploadPartInput+presignURL.swift +++ b/AmplifyPlugins/Storage/Sources/AWSS3StoragePlugin/Dependency/UploadPartInput+presignURL.swift @@ -5,12 +5,13 @@ // SPDX-License-Identifier: Apache-2.0 import Foundation -@testable import AWSS3 +import AWSS3 @_spi(SmithyReadWrite) import ClientRuntime -import AWSClientRuntime +@_spi(UnknownAWSHTTPServiceError) @_spi(SmithyReadWrite) import AWSClientRuntime import Smithy import SmithyHTTPAPI import SmithyRetries +@_spi(SmithyReadWrite) import SmithyXML // swiftlint:disable identifier_name // swiftlint:disable line_length @@ -29,7 +30,7 @@ extension UploadPartInput { .withServiceName(value: serviceName) .withOperation(value: "uploadPart") .withIdempotencyTokenGenerator(value: config.idempotencyTokenGenerator) - .withLogger(value: config.logger) + .withLogger(value: config.telemetryProvider.loggerProvider.getLogger(name: S3Client.clientName)) .withPartitionID(value: config.partitionID) .withAuthSchemes(value: config.authSchemes ?? []) .withAuthSchemeResolver(value: config.authSchemeResolver) @@ -52,9 +53,9 @@ extension UploadPartInput { config.httpInterceptorProviders.forEach { provider in builder.interceptors.add(provider.create()) } - builder.interceptors.add(ClientRuntime.URLPathMiddleware(UploadPartInput.urlPathProvider(_:))) + builder.interceptors.add(ClientRuntime.URLPathMiddleware(UploadPartInput.customUrlPathProvider(_:))) builder.interceptors.add(ClientRuntime.URLHostMiddleware()) - builder.deserialize(ClientRuntime.DeserializeMiddleware(UploadPartOutput.httpOutput(from:), PutObjectOutputError.httpError(from:))) + builder.deserialize(ClientRuntime.DeserializeMiddleware(UploadPartOutput.customHttpOutput(from:), CustomUploadPartOutputError.httpError(from:))) builder.interceptors.add(ClientRuntime.LoggerMiddleware(clientLogMode: config.clientLogMode)) builder.retryStrategy(SmithyRetries.DefaultRetryStrategy(options: config.retryStrategyOptions)) builder.retryErrorInfoProvider(AWSClientRuntime.AWSRetryErrorInfoProvider.errorInfo(for:)) @@ -80,9 +81,89 @@ extension UploadPartInput { .build() return try await op.presignRequest(input: input).endpoint.url } - } +} + +private extension UploadPartInput { + static func customUrlPathProvider(_ value: UploadPartInput) -> Swift.String? { + guard let key = value.key else { + return nil + } + return "/\(key.urlPercentEncoding(encodeForwardSlash: false))" + } +} + +private extension UploadPartOutput { + static func customHttpOutput(from httpResponse: SmithyHTTPAPI.HTTPResponse) async throws -> UploadPartOutput { + var value = UploadPartOutput() + if let bucketKeyEnabledHeaderValue = httpResponse.headers.value(for: "x-amz-server-side-encryption-bucket-key-enabled") { + value.bucketKeyEnabled = Swift.Bool(bucketKeyEnabledHeaderValue) ?? false + } + if let checksumCRC32HeaderValue = httpResponse.headers.value(for: "x-amz-checksum-crc32") { + value.checksumCRC32 = checksumCRC32HeaderValue + } + if let checksumCRC32CHeaderValue = httpResponse.headers.value(for: "x-amz-checksum-crc32c") { + value.checksumCRC32C = checksumCRC32CHeaderValue + } + if let checksumSHA1HeaderValue = httpResponse.headers.value(for: "x-amz-checksum-sha1") { + value.checksumSHA1 = checksumSHA1HeaderValue + } + if let checksumSHA256HeaderValue = httpResponse.headers.value(for: "x-amz-checksum-sha256") { + value.checksumSHA256 = checksumSHA256HeaderValue + } + if let eTagHeaderValue = httpResponse.headers.value(for: "ETag") { + value.eTag = eTagHeaderValue + } + if let requestChargedHeaderValue = httpResponse.headers.value(for: "x-amz-request-charged") { + value.requestCharged = S3ClientTypes.RequestCharged(rawValue: requestChargedHeaderValue) + } + if let sseCustomerAlgorithmHeaderValue = httpResponse.headers.value(for: "x-amz-server-side-encryption-customer-algorithm") { + value.sseCustomerAlgorithm = sseCustomerAlgorithmHeaderValue + } + if let sseCustomerKeyMD5HeaderValue = httpResponse.headers.value(for: "x-amz-server-side-encryption-customer-key-MD5") { + value.sseCustomerKeyMD5 = sseCustomerKeyMD5HeaderValue + } + if let ssekmsKeyIdHeaderValue = httpResponse.headers.value(for: "x-amz-server-side-encryption-aws-kms-key-id") { + value.ssekmsKeyId = ssekmsKeyIdHeaderValue + } + if let serverSideEncryptionHeaderValue = httpResponse.headers.value(for: "x-amz-server-side-encryption") { + value.serverSideEncryption = S3ClientTypes.ServerSideEncryption(rawValue: serverSideEncryptionHeaderValue) + } + return value + } +} + +private enum CustomUploadPartOutputError { + static func httpError(from httpResponse: SmithyHTTPAPI.HTTPResponse) async throws -> Swift.Error { + let data = try await httpResponse.data() + let responseReader = try SmithyXML.Reader.from(data: data) + let baseError = try AWSClientRuntime.RestXMLError(httpResponse: httpResponse, responseReader: responseReader, noErrorWrapping: true) + if let error = baseError.customError() { return error } + if baseError.httpResponse.statusCode == .notFound && baseError.httpResponse.body.isEmpty { + return CustomUploadPartOutputError.NotFound( + httpResponse: baseError.httpResponse, + message: baseError.requestID, + requestID: baseError.message, + requestID2: baseError.requestID2 + ) + } + switch baseError.code { + default: return try AWSClientRuntime.UnknownAWSHTTPServiceError.makeError(baseError: baseError) + } + } + + private struct NotFound: ClientRuntime.ModeledError, AWSClientRuntime.AWSS3ServiceError, ClientRuntime.HTTPError, Swift.Error { + static var typeName: Swift.String { "NotFound" } + static var fault: ClientRuntime.ErrorFault { .client } + static var isRetryable: Swift.Bool { false } + static var isThrottling: Swift.Bool { false } + var httpResponse = SmithyHTTPAPI.HTTPResponse() + var message: Swift.String? + var requestID: Swift.String? + var requestID2: Swift.String? + } +} -struct UploadPartPresignedMiddleware: Smithy.RequestMessageSerializer { +private struct UploadPartPresignedMiddleware: Smithy.RequestMessageSerializer { typealias InputType = UploadPartInput typealias RequestType = SmithyHTTPAPI.HTTPRequest