Skip to content

Commit

Permalink
chore: merge most recent main into I&A project branch (#638)
Browse files Browse the repository at this point in the history
* chore: Require Swift 5.7, fix deprecation warnings (#600)

* feat: support initial-response in RPC based event streams (#597)

* chore: Updates version to 0.32.0

* chore: Add newline to README.md (#602)

* feat: add limited support in smithy-swift for visionOS (#606)

* feat: add support for requiresLength trait and Transfer-Encoding: Chunked (#604)

* chore: Update to aws-crt-swift 0.15.0 (#607)

* fix: content-length middleware should not error on event streams (#608)

* chore: Updates version to 0.33.0

* chore: Improved downstream task (#568)

* chore: Convert idempotency token middleware from closure to reusable type (#610)

* fix: Update aws-crt-swift dependency to 0.17.0 (#612)

* chore: Updates version to 0.34.0

* fix: Endpoint url should be nil if host or scheme is missing (#614)

* fix: Pool HTTP connections based on scheme, host, and port (#615)

* add default log level to initialize method (#616)

* feat: add utility method for converting SdkHttpRequest to URLRequest. (#613)

* Add extension constructor to URLRequest to convert SDKHttpRequest

* Add preprocessor conditional import functionality to SwiftWriter.

---------

Co-authored-by: Sichan Yoo <chanyoo@amazon.com>

* chore: Updates version to 0.35.0

* fix: Add a header to operation doc comments (#621)

* remove unnecessary TODOs (#622)

* fix: Codegen issues re: recursion, Swift keywords in unions (#623)

* feat!: Replace the XML encoder with a custom Smithy implementation (#619)

* feat!: Use closures for processing HTTP response (#624)

* feat: add custom trait PaginationTruncationMember (#625)

* allow isTruncated to be optional bool (#626)

* chore: Updates version to 0.36.0

* chore: Run tvOS old & new in CI (#628)

* fix: Fix Package.swift warning on Mac (#629)

* chore: refactor HttpBody and ByteStream to be a single class ByteStream (#627)

* chore: remove sync read in unused data extension (#630)

* update smithy to 1.42.0 (#631)

* chore: Updates version to 0.37.0

* chore: Update to aws-crt-swift 0.20.0 (#633)

* fix: add back from method with fileHandle (#635)

* fix!: Add no-op behavior for initialize methods of logging system. (#637)

* Add no-op behavior for initialize methods if it isn't the first time being called.

* Make LockingSystem threadsafe.

* Make initialize methods async.

---------

Co-authored-by: Sichan Yoo <chanyoo@amazon.com>

* feat!: URLSession-based HTTP Client (#636)

* Delete missed merge conflict marker.

---------

Co-authored-by: Josh Elkins <jbelkins@users.noreply.github.com>
Co-authored-by: David Yaffe <dayaffe@amazon.com>
Co-authored-by: AWS SDK Swift Automation <github-aws-sdk-swift-automation@amazon.com>
Co-authored-by: Cyprien Ricque <48893621+CyprienRicque@users.noreply.github.com>
Co-authored-by: Sichan Yoo <chanyoo@amazon.com>
  • Loading branch information
6 people authored Jan 11, 2024
1 parent 63ddd3b commit b5868d8
Show file tree
Hide file tree
Showing 200 changed files with 3,863 additions and 4,394 deletions.
25 changes: 16 additions & 9 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,29 @@ jobs:
- macos-13
xcode:
- Xcode_14.0.1
- Xcode_15.0
- Xcode_15.1
destination:
- 'platform=iOS Simulator,OS=16.0,name=iPhone 13'
- 'platform=iOS Simulator,OS=17.0,name=iPhone 15'
- 'platform=iOS Simulator,OS=16.0,name=iPhone 14'
- 'platform=iOS Simulator,OS=17.2,name=iPhone 15'
- 'platform=tvOS Simulator,OS=16.0,name=Apple TV 4K (at 1080p) (2nd generation)'
- 'platform=tvOS Simulator,OS=17.2,name=Apple TV 4K (3rd generation) (at 1080p)'
- 'platform=OS X'
exclude:
# Don't run old macOS with new Xcode
- runner: macos-12
xcode: Xcode_15.0
xcode: Xcode_15.1
# Don't run new macOS with old Xcode
- runner: macos-13
xcode: Xcode_14.0.1
# Don't run old iOS simulator with new Xcode
- destination: 'platform=iOS Simulator,OS=16.0,name=iPhone 13'
xcode: Xcode_15.0
# Don't run new iOS simulator with old Xcode
- destination: 'platform=iOS Simulator,OS=17.0,name=iPhone 15'
# Don't run old iOS/tvOS simulator with new Xcode
- destination: 'platform=iOS Simulator,OS=16.0,name=iPhone 14'
xcode: Xcode_15.1
- destination: 'platform=tvOS Simulator,OS=16.0,name=Apple TV 4K (at 1080p) (2nd generation)'
xcode: Xcode_15.1
# Don't run new iOS/tvOS simulator with old Xcode
- destination: 'platform=iOS Simulator,OS=17.2,name=iPhone 15'
xcode: Xcode_14.0.1
- destination: 'platform=tvOS Simulator,OS=17.2,name=Apple TV 4K (3rd generation) (at 1080p)'
xcode: Xcode_14.0.1
steps:
- name: Checkout smithy-swift
Expand Down Expand Up @@ -89,6 +95,7 @@ jobs:
- name: Build & Run smithy-swift Kotlin Unit Tests
run: ./gradlew build
- name: Build & Run smithy-swift Swift Unit Tests
timeout-minutes: 15
run: |
set -o pipefail && \
NSUnbufferedIO=YES xcodebuild \
Expand Down
2 changes: 2 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ excluded:
- Sources/SmithyTestUtil/*
- Tests/ClientRuntimeTests/*
- Tests/SmithyTestUtilTests/*
- Tests/SmithyXMLTests/*
- Tests/SmithyTimestampsTests/*

analyzer_rules:
- unused_import
Expand Down
59 changes: 51 additions & 8 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,84 @@

import PackageDescription

// Define libxml2 only on Linux, since it causes warnings
// about "pkgconfig not found" on Mac
#if os(Linux)
let libXML2DependencyOrNil: Target.Dependency? = "libxml2"
let libXML2TargetOrNil: Target? = Target.systemLibrary(
name: "libxml2",
pkgConfig: "libxml-2.0",
providers: [
.apt(["libxml2 libxml2-dev"]),
.yum(["libxml2 libxml2-devel"])
]
)
#else
let libXML2DependencyOrNil: Target.Dependency? = nil
let libXML2TargetOrNil: Target? = nil
#endif

let package = Package(
name: "smithy-swift",
platforms: [
.macOS(.v10_15),
.iOS(.v13)
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6)
],
products: [
.library(name: "ClientRuntime", targets: ["ClientRuntime"]),
.library(name: "SmithyTestUtil", targets: ["SmithyTestUtil"])
.library(name: "SmithyReadWrite", targets: ["SmithyReadWrite"]),
.library(name: "SmithyXML", targets: ["SmithyXML"]),
.library(name: "SmithyTestUtil", targets: ["SmithyTestUtil"]),
],
dependencies: [
.package(url: "https://github.com/awslabs/aws-crt-swift.git", exact: "0.17.0"),
.package(url: "https://github.com/awslabs/aws-crt-swift.git", exact: "0.20.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/MaxDesiatov/XMLCoder.git", exact: "0.17.0")
],
targets: [
.target(
name: "ClientRuntime",
dependencies: [
"SmithyXML",
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift"),
.product(name: "Logging", package: "swift-log"),
.product(name: "XMLCoder", package: "XMLCoder")
]
),
.testTarget(
name: "ClientRuntimeTests",
dependencies: ["ClientRuntime", "SmithyTestUtil"]
.target(name: "SmithyReadWrite"),
.target(
name: "SmithyXML",
dependencies: [
"SmithyReadWrite",
"SmithyTimestamps",
libXML2DependencyOrNil
].compactMap { $0 }
),
libXML2TargetOrNil,
.target(
name: "SmithyTimestamps"
),
.target(
name: "SmithyTestUtil",
dependencies: ["ClientRuntime"]
),
.testTarget(
name: "ClientRuntimeTests",
dependencies: ["ClientRuntime", "SmithyTestUtil"]
),
.testTarget(
name: "SmithyXMLTests",
dependencies: ["SmithyXML"]
),
.testTarget(
name: "SmithyTimestampsTests",
dependencies: ["SmithyTimestamps"]
),
.testTarget(
name: "SmithyTestUtilTests",
dependencies: ["SmithyTestUtil"]
)
]
),
].compactMap { $0 }
)
2 changes: 1 addition & 1 deletion Package.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.35.0
0.37.0
24 changes: 13 additions & 11 deletions Sources/ClientRuntime/Config/DefaultSDKRuntimeConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public struct DefaultSDKRuntimeConfiguration<DefaultSDKRuntimeRetryStrategy: Ret
/// The HTTP client to be used for HTTP connections.
///
/// If none is provided, the AWS CRT HTTP client will be used.
public var httpClientEngine: HttpClientEngine
public var httpClientEngine: HTTPClient

/// The HTTP client configuration.
///
Expand Down Expand Up @@ -72,8 +72,8 @@ public struct DefaultSDKRuntimeConfiguration<DefaultSDKRuntimeRetryStrategy: Ret
self.clientName = clientName
self.encoder = nil
self.decoder = nil
self.httpClientEngine = Self.defaultHttpClientEngine
self.httpClientConfiguration = Self.defaultHttpClientConfiguration
self.httpClientEngine = Self.makeClient(httpClientConfiguration: self.httpClientConfiguration)
self.idempotencyTokenGenerator = Self.defaultIdempotencyTokenGenerator
self.retryStrategyOptions = Self.defaultRetryStrategyOptions
self.logger = Self.defaultLogger(clientName: clientName)
Expand All @@ -85,16 +85,18 @@ public struct DefaultSDKRuntimeConfiguration<DefaultSDKRuntimeRetryStrategy: Ret
// Exposing these as static properties/methods allows them to be used by custom config objects.
public extension DefaultSDKRuntimeConfiguration {

/// The default HTTP client to use when none is configured
/// The default HTTP client for the target platform, configured with the supplied configuration.
///
/// Is the CRT HTTP client.
static var defaultHttpClientEngine: HttpClientEngine { CRTClientEngine() }

/// The default HTTP client with a specified timeout
///
/// Is the CRT HTTP client.
static func httpClientEngineWithTimeout(timeoutMs: UInt32) -> HttpClientEngine {
return CRTClientEngine(config: CRTClientEngineConfig(connectTimeoutMs: timeoutMs))
/// - Parameter httpClientConfiguration: The configuration for the HTTP client.
/// - Returns: The `CRTClientEngine` client on Mac & Linux platforms, returns `URLSessionHttpClient` on non-Mac Apple platforms.
static func makeClient(httpClientConfiguration: HttpClientConfiguration) -> HTTPClient {
#if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
return URLSessionHTTPClient(httpClientConfiguration: httpClientConfiguration)
#else
let connectTimeoutMs = httpClientConfiguration.connectTimeout.map { UInt32($0 * 1_000_000) }
let config = CRTClientEngineConfig(connectTimeoutMs: connectTimeoutMs)
return CRTClientEngine(config: config)
#endif
}

/// The HTTP client configuration to use when none is provided.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ extension EventStream {
public struct DefaultMessageDecoderStream<Event: MessageUnmarshallable>: MessageDecoderStream {
public typealias Element = Event

let stream: Stream
let stream: ReadableStream
let messageDecoder: MessageDecoder
let responseDecoder: ResponseDecoder

public init(stream: Stream, messageDecoder: MessageDecoder, responseDecoder: ResponseDecoder) {
public init(stream: ReadableStream, messageDecoder: MessageDecoder, responseDecoder: ResponseDecoder) {
self.stream = stream
self.messageDecoder = messageDecoder
self.responseDecoder = responseDecoder
}

public struct AsyncIterator: AsyncIteratorProtocol {
let stream: Stream
let stream: ReadableStream
let messageDecoder: MessageDecoder
let responseDecoder: ResponseDecoder

init(stream: Stream, messageDecoder: MessageDecoder, responseDecoder: ResponseDecoder) {
init(stream: ReadableStream, messageDecoder: MessageDecoder, responseDecoder: ResponseDecoder) {
self.stream = stream
self.messageDecoder = messageDecoder
self.responseDecoder = responseDecoder
Expand Down
30 changes: 19 additions & 11 deletions Sources/ClientRuntime/EventStream/DefaultMessageEncoderStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,27 @@ extension EventStream {
public class DefaultMessageEncoderStream<Event: MessageMarshallable>: MessageEncoderStream, Stream {
let stream: AsyncThrowingStream<Event, Error>
let messageEncoder: MessageEncoder
let messageSinger: MessageSigner
let messageSigner: MessageSigner
let requestEncoder: RequestEncoder
var readAsyncIterator: AsyncIterator?

public init(
stream: AsyncThrowingStream<Event, Error>,
messageEncoder: MessageEncoder,
requestEncoder: RequestEncoder,
messageSinger: MessageSigner
messageSigner: MessageSigner
) {
self.stream = stream
self.messageEncoder = messageEncoder
self.messageSinger = messageSinger
self.messageSigner = messageSigner
self.requestEncoder = requestEncoder
self.readAsyncIterator = makeAsyncIterator()
}

public struct AsyncIterator: AsyncIteratorProtocol {
let stream: AsyncThrowingStream<Event, Error>
let messageEncoder: MessageEncoder
var messageSinger: MessageSigner
var messageSigner: MessageSigner
let requestEncoder: RequestEncoder

private var lastMessageSent: Bool = false
Expand All @@ -42,12 +42,12 @@ extension EventStream {
stream: AsyncThrowingStream<Event, Error>,
messageEncoder: MessageEncoder,
requestEncoder: RequestEncoder,
messageSinger: MessageSigner
messageSigner: MessageSigner
) {
self.stream = stream
self.streamIterator = stream.makeAsyncIterator()
self.messageEncoder = messageEncoder
self.messageSinger = messageSinger
self.messageSigner = messageSigner
self.requestEncoder = requestEncoder
}

Expand All @@ -56,7 +56,7 @@ extension EventStream {
// There are no more messages in the base stream
// if we have not sent the last message, send it now
guard lastMessageSent else {
let emptySignedMessage = try await messageSinger.signEmpty()
let emptySignedMessage = try await messageSigner.signEmpty()
let data = try messageEncoder.encode(message: emptySignedMessage)
lastMessageSent = true
return data
Expand All @@ -70,7 +70,7 @@ extension EventStream {
let message = try event.marshall(encoder: requestEncoder)

// sign the message
let signedMessage = try await messageSinger.sign(message: message)
let signedMessage = try await messageSigner.sign(message: message)

// encode again the signed message
let data = try messageEncoder.encode(message: signedMessage)
Expand All @@ -83,7 +83,7 @@ extension EventStream {
stream: stream,
messageEncoder: messageEncoder,
requestEncoder: requestEncoder,
messageSinger: messageSinger
messageSigner: messageSigner
)
}

Expand Down Expand Up @@ -114,7 +114,11 @@ extension EventStream {
}

public func readToEndAsync() async throws -> ClientRuntime.Data? {
fatalError("readToEndAsync() is not supported by AsyncStream backed streams")
var data = Data()
while let moreData = try await readAsync(upToCount: Int.max) {
data.append(moreData)
}
return data
}

/// Reads up to `count` bytes from the stream asynchronously
Expand Down Expand Up @@ -167,7 +171,11 @@ extension EventStream {
}

/// Closing the stream is a no-op because the underlying async stream is not owned by this stream
public func close() throws {
public func close() {
// no-op
}

public func closeWithError(_ error: Error) {
// no-op
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct IdempotencyTokenMiddleware<OperationStackInput,
OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseErrorBinding>: ClientRuntime.Middleware {
public struct IdempotencyTokenMiddleware<OperationStackInput, OperationStackOutput>: ClientRuntime.Middleware {
public let id: Swift.String = "IdempotencyTokenMiddleware"
private let keyPath: WritableKeyPath<OperationStackInput, String?>

Expand Down
11 changes: 7 additions & 4 deletions Sources/ClientRuntime/Logging/SDKLoggingSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@

import Logging

public class SDKLoggingSystem {
public actor SDKLoggingSystem {
private static var isInitialized = false
private static var factories: [String: SDKLogHandlerFactory] = [:]

public class func add(logHandlerFactory: SDKLogHandlerFactory) {
public static func add(logHandlerFactory: SDKLogHandlerFactory) {
let label = logHandlerFactory.label
factories[label] = logHandlerFactory
}

public class func initialize(defaultLogLevel: SDKLogLevel = .info) {
public static func initialize(defaultLogLevel: SDKLogLevel = .info) async {
if isInitialized { return } else { isInitialized = true }
LoggingSystem.bootstrap { label in
if let factory = factories[label] {
return factory.construct(label: label)
Expand All @@ -26,7 +28,8 @@ public class SDKLoggingSystem {
}
}

public class func initialize(logLevel: SDKLogLevel) {
public static func initialize(logLevel: SDKLogLevel) async {
if isInitialized { return } else { isInitialized = true }
LoggingSystem.bootstrap { label in
var handler = StreamLogHandler.standardOutput(label: label)
handler.logLevel = logLevel.toLoggerType()
Expand Down
9 changes: 6 additions & 3 deletions Sources/ClientRuntime/Middleware/NoopHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
// SPDX-License-Identifier: Apache-2.0
//

public struct NoopHandler<Output: HttpResponseBinding>: Handler {
public struct NoopHandler<OperationStackOutput>: Handler {
public init() {}

public func handle(context: HttpContext, input: SdkHttpRequest) async throws -> OperationOutput<Output> {
return OperationOutput<Output>(httpResponse: HttpResponse())
public func handle(
context: HttpContext,
input: SdkHttpRequest
) async throws -> OperationOutput<OperationStackOutput> {
return OperationOutput<OperationStackOutput>(httpResponse: HttpResponse())
}
}
Loading

0 comments on commit b5868d8

Please sign in to comment.