Skip to content

Commit de685ac

Browse files
authored
chore: kickoff release
2 parents 999a93e + 6fa88d4 commit de685ac

File tree

10 files changed

+285
-7
lines changed

10 files changed

+285
-7
lines changed

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import AWSCognitoIdentity
1212
import AWSCognitoIdentityProvider
1313
import AWSPluginsCore
1414
import ClientRuntime
15+
@_spi(FoundationClientEngine) import AWSPluginsCore
1516

1617
extension AWSCognitoAuthPlugin {
1718

@@ -92,9 +93,23 @@ extension AWSCognitoAuthPlugin {
9293
)
9394

9495
if var httpClientEngineProxy = httpClientEngineProxy {
95-
let sdkEngine = configuration.httpClientEngine
96-
httpClientEngineProxy.target = sdkEngine
96+
let httpClientEngine: HttpClientEngine
97+
#if os(iOS) || os(macOS)
98+
// networking goes through CRT
99+
httpClientEngine = configuration.httpClientEngine
100+
#else
101+
// networking goes through Foundation
102+
httpClientEngine = FoundationClientEngine()
103+
#endif
104+
httpClientEngineProxy.target = httpClientEngine
97105
configuration.httpClientEngine = httpClientEngineProxy
106+
} else {
107+
#if os(iOS) || os(macOS) // no-op
108+
#else
109+
// For any platform except iOS or macOS
110+
// Use Foundation instead of CRT for networking.
111+
configuration.httpClientEngine = FoundationClientEngine()
112+
#endif
98113
}
99114

100115
return CognitoIdentityProviderClient(config: configuration)
@@ -110,6 +125,14 @@ extension AWSCognitoAuthPlugin {
110125
frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData(),
111126
region: identityPoolConfig.region
112127
)
128+
129+
#if os(iOS) || os(macOS) // no-op
130+
#else
131+
// For any platform except iOS or macOS
132+
// Use Foundation instead of CRT for networking.
133+
configuration.httpClientEngine = FoundationClientEngine()
134+
#endif
135+
113136
return CognitoIdentityClient(config: configuration)
114137
default:
115138
fatalError()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import ClientRuntime
10+
11+
extension Foundation.URLRequest {
12+
init(sdkRequest: ClientRuntime.SdkHttpRequest) throws {
13+
guard let url = sdkRequest.endpoint.url else {
14+
throw FoundationClientEngineError.invalidRequestURL(sdkRequest: sdkRequest)
15+
}
16+
self.init(url: url)
17+
httpMethod = sdkRequest.method.rawValue
18+
19+
for header in sdkRequest.headers.headers {
20+
for value in header.value {
21+
addValue(value, forHTTPHeaderField: header.name)
22+
}
23+
}
24+
25+
switch sdkRequest.body {
26+
case .data(let data): httpBody = data
27+
case .stream(let stream): httpBody = stream.toBytes().getData()
28+
case .none: break
29+
}
30+
}
31+
}
32+
33+
extension ClientRuntime.HttpResponse {
34+
private static func headers(
35+
from allHeaderFields: [AnyHashable: Any]
36+
) -> ClientRuntime.Headers {
37+
var headers = Headers()
38+
for header in allHeaderFields {
39+
switch (header.key, header.value) {
40+
case let (key, value) as (String, String):
41+
headers.add(name: key, value: value)
42+
case let (key, values) as (String, [String]):
43+
headers.add(name: key, values: values)
44+
default: continue
45+
}
46+
}
47+
return headers
48+
}
49+
50+
convenience init(httpURLResponse: HTTPURLResponse, data: Data) throws {
51+
let headers = Self.headers(from: httpURLResponse.allHeaderFields)
52+
let body = HttpBody.stream(ByteStream.from(data: data))
53+
54+
guard let statusCode = HttpStatusCode(rawValue: httpURLResponse.statusCode) else {
55+
// This shouldn't happen, but `HttpStatusCode` only exposes a failable
56+
// `init`. The alternative here is force unwrapping, but we can't
57+
// make the decision to crash here on behalf on consuming applications.
58+
throw FoundationClientEngineError.unexpectedStatusCode(
59+
statusCode: httpURLResponse.statusCode
60+
)
61+
}
62+
self.init(headers: headers, body: body, statusCode: statusCode)
63+
}
64+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import ClientRuntime
10+
import Amplify
11+
12+
@_spi(FoundationClientEngine)
13+
public struct FoundationClientEngine: HttpClientEngine {
14+
public func execute(request: ClientRuntime.SdkHttpRequest) async throws -> ClientRuntime.HttpResponse {
15+
let urlRequest = try URLRequest(sdkRequest: request)
16+
17+
let (data, response) = try await URLSession.shared.data(for: urlRequest)
18+
guard let httpURLResponse = response as? HTTPURLResponse else {
19+
// This shouldn't be necessary because we're only making HTTP requests.
20+
// `URLResponse` should always be a `HTTPURLResponse`.
21+
// But to refrain from crashing consuming applications, we're throwing here.
22+
throw FoundationClientEngineError.invalidURLResponse(urlRequest: response)
23+
}
24+
25+
let httpResponse = try HttpResponse(
26+
httpURLResponse: httpURLResponse,
27+
data: data
28+
)
29+
30+
return httpResponse
31+
}
32+
33+
public init() {}
34+
35+
/// no-op
36+
func close() async {}
37+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import Amplify
10+
import ClientRuntime
11+
12+
struct FoundationClientEngineError: AmplifyError {
13+
let errorDescription: ErrorDescription
14+
let recoverySuggestion: RecoverySuggestion
15+
let underlyingError: Error?
16+
17+
// protocol requirement
18+
init(
19+
errorDescription: ErrorDescription,
20+
recoverySuggestion: RecoverySuggestion,
21+
error: Error
22+
) {
23+
self.errorDescription = errorDescription
24+
self.recoverySuggestion = recoverySuggestion
25+
self.underlyingError = error
26+
}
27+
}
28+
29+
extension FoundationClientEngineError {
30+
init(
31+
errorDescription: ErrorDescription,
32+
recoverySuggestion: RecoverySuggestion,
33+
error: Error?
34+
) {
35+
self.errorDescription = errorDescription
36+
self.recoverySuggestion = recoverySuggestion
37+
self.underlyingError = error
38+
}
39+
40+
static func invalidRequestURL(sdkRequest: ClientRuntime.SdkHttpRequest) -> Self {
41+
.init(
42+
errorDescription: """
43+
The SdkHttpRequest generated by ClientRuntime doesn't include a valid URL
44+
- \(sdkRequest)
45+
""",
46+
recoverySuggestion: """
47+
Please open an issue at https://github.com/aws-amplify/amplify-swift
48+
with the contents of this error message.
49+
""",
50+
error: nil
51+
)
52+
}
53+
54+
static func invalidURLResponse(urlRequest: URLResponse) -> Self {
55+
.init(
56+
errorDescription: """
57+
The URLResponse received is not an HTTPURLResponse
58+
- \(urlRequest)
59+
""",
60+
recoverySuggestion: """
61+
Please open an issue at https://github.com/aws-amplify/amplify-swift
62+
with the contents of this error message.
63+
""",
64+
error: nil
65+
)
66+
}
67+
68+
static func unexpectedStatusCode(statusCode: Int) -> Self {
69+
.init(
70+
errorDescription: """
71+
The status code received isn't a valid `HttpStatusCode` value.
72+
- status code: \(statusCode)
73+
""",
74+
recoverySuggestion: """
75+
Please open an issue at https://github.com/aws-amplify/amplify-swift
76+
with the contents of this error message.
77+
""",
78+
error: nil
79+
)
80+
}
81+
}

AmplifyPlugins/Geo/Sources/AWSLocationGeoPlugin/AWSLocationGeoPlugin+Configure.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
// SPDX-License-Identifier: Apache-2.0
66
//
77

8+
import Foundation
89
import Amplify
910
import AWSPluginsCore
10-
import Foundation
11-
11+
@_spi(FoundationClientEngine) import AWSPluginsCore
1212
import AWSLocation
1313
import AWSClientRuntime
1414

@@ -35,6 +35,13 @@ extension AWSLocationGeoPlugin {
3535
frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData(),
3636
region: region)
3737

38+
#if os(iOS) || os(macOS) // no-op
39+
#else
40+
// For any platform except iOS or macOS
41+
// Use Foundation instead of CRT for networking.
42+
serviceConfiguration.httpClientEngine = FoundationClientEngine()
43+
#endif
44+
3845
let location = LocationClient(config: serviceConfiguration)
3946
let locationService = AWSLocationAdapter(location: location)
4047

AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/PinpointClient+CredentialsProvider.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import AWSClientRuntime
99
import AWSPluginsCore
1010
import AWSPinpoint
11+
@_spi(FoundationClientEngine) import AWSPluginsCore
1112

1213
extension PinpointClient {
1314
convenience init(region: String, credentialsProvider: CredentialsProvider) throws {
@@ -16,6 +17,12 @@ extension PinpointClient {
1617
frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData(),
1718
region: region
1819
)
20+
#if os(iOS) || os(macOS) // no-op
21+
#else
22+
// For any platform except iOS or macOS
23+
// Use Foundation instead of CRT for networking.
24+
configuration.httpClientEngine = FoundationClientEngine()
25+
#endif
1926
PinpointRequestsRegistry.shared.setCustomHttpEngine(on: configuration)
2027
self.init(config: configuration)
2128
}

AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/PinpointRequestsRegistry.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import ClientRuntime
2020
}
2121

2222
nonisolated func setCustomHttpEngine(on configuration: PinpointClient.PinpointClientConfiguration) {
23-
let oldHttpClientEngine = configuration.httpClientEngine
23+
let baseHTTPClientEngine = configuration.httpClientEngine
24+
2425
configuration.httpClientEngine = CustomPinpointHttpClientEngine(
25-
httpClientEngine: oldHttpClientEngine
26+
httpClientEngine: baseHTTPClientEngine
2627
)
2728
}
2829

AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/AWSCloudWatchLoggingSessionController.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77

88
import AWSPluginsCore
9+
@_spi(FoundationClientEngine) import AWSPluginsCore
910
import Amplify
1011
import Combine
1112
import Foundation
@@ -107,6 +108,14 @@ final class AWSCloudWatchLoggingSessionController {
107108
frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData(),
108109
region: region
109110
)
111+
112+
#if os(iOS) || os(macOS) // no-op
113+
#else
114+
// For any platform except iOS or macOS
115+
// Use Foundation instead of CRT for networking.
116+
configuration.httpClientEngine = FoundationClientEngine()
117+
#endif
118+
110119
self.client = CloudWatchLogsClient(config: configuration)
111120
}
112121

AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import AWSTextract
1212
import AWSComprehend
1313
import AWSPolly
1414
import AWSPluginsCore
15+
@_spi(FoundationClientEngine) import AWSPluginsCore
1516
import Foundation
1617
import ClientRuntime
1718
import AWSClientRuntime
@@ -37,30 +38,60 @@ class AWSPredictionsService {
3738
credentialsProvider: credentialsProvider,
3839
region: configuration.convert.region
3940
)
41+
#if os(iOS) || os(macOS) // no-op
42+
#else
43+
// For any platform except iOS or macOS
44+
// Use Foundation instead of CRT for networking.
45+
translateClientConfiguration.httpClientEngine = FoundationClientEngine()
46+
#endif
4047
let awsTranslateClient = TranslateClient(config: translateClientConfiguration)
4148

4249
let pollyClientConfiguration = try PollyClient.PollyClientConfiguration(
4350
credentialsProvider: credentialsProvider,
4451
region: configuration.convert.region
4552
)
53+
#if os(iOS) || os(macOS) // no-op
54+
#else
55+
// For any platform except iOS or macOS
56+
// Use Foundation instead of CRT for networking.
57+
pollyClientConfiguration.httpClientEngine = FoundationClientEngine()
58+
#endif
4659
let awsPollyClient = PollyClient(config: pollyClientConfiguration)
4760

4861
let comprehendClientConfiguration = try ComprehendClient.ComprehendClientConfiguration(
4962
credentialsProvider: credentialsProvider,
5063
region: configuration.convert.region
5164
)
65+
#if os(iOS) || os(macOS) // no-op
66+
#else
67+
// For any platform except iOS or macOS
68+
// Use Foundation instead of CRT for networking.
69+
comprehendClientConfiguration.httpClientEngine = FoundationClientEngine()
70+
#endif
5271
let awsComprehendClient = ComprehendClient(config: comprehendClientConfiguration)
5372

5473
let rekognitionClientConfiguration = try RekognitionClient.RekognitionClientConfiguration(
5574
credentialsProvider: credentialsProvider,
5675
region: configuration.identify.region
5776
)
77+
#if os(iOS) || os(macOS) // no-op
78+
#else
79+
// For any platform except iOS or macOS
80+
// Use Foundation instead of CRT for networking.
81+
rekognitionClientConfiguration.httpClientEngine = FoundationClientEngine()
82+
#endif
5883
let awsRekognitionClient = RekognitionClient(config: rekognitionClientConfiguration)
5984

6085
let textractClientConfiguration = try TextractClient.TextractClientConfiguration(
6186
credentialsProvider: credentialsProvider,
6287
region: configuration.identify.region
6388
)
89+
#if os(iOS) || os(macOS) // no-op
90+
#else
91+
// For any platform except iOS or macOS
92+
// Use Foundation instead of CRT for networking.
93+
textractClientConfiguration.httpClientEngine = FoundationClientEngine()
94+
#endif
6495
let awsTextractClient = TextractClient(config: textractClientConfiguration)
6596

6697
let awsTranscribeStreamingAdapter = AWSTranscribeStreamingAdapter(

0 commit comments

Comments
 (0)