Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Use only FoundationEssentials #628

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Benchmark/Sources/soto-benchmark/AWSClientSuite.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@

import Benchmark
import Dispatch
import Foundation
import NIO
import SotoCore

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

struct RequestThrowMiddleware: AWSServiceMiddleware {
struct Error: Swift.Error {}

Expand Down
7 changes: 6 additions & 1 deletion Benchmark/Sources/soto-benchmark/AWSSignerV4Suite.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
//===----------------------------------------------------------------------===//

import Benchmark
import Foundation
import SotoSignerV4

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

let awsSignerV4Suite = BenchmarkSuite(name: "AWSSignerV4", settings: Iterations(1000), WarmupIterations(2)) { suite in
let string = "testing, testing, 1,2,1,2"
let credentials: Credential = StaticCredential(accessKeyId: "MYACCESSKEY", secretAccessKey: "MYSECRETACCESSKEY")
Expand Down
7 changes: 6 additions & 1 deletion Benchmark/Sources/soto-benchmark/EncoderSuites.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
//===----------------------------------------------------------------------===//

import Benchmark
import Foundation
import SotoCore

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

#if compiler(>=5.10)
internal import SotoXML
#else
Expand Down
7 changes: 7 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ let package = Package(
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "JMESPath", package: "jmespath.swift"),
.product(name: "Tracing", package: "swift-distributed-tracing"),
"SotoUtils",
],
swiftSettings: swiftSettings
),
Expand All @@ -73,9 +74,15 @@ let package = Package(
.product(name: "Crypto", package: "swift-crypto"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOHTTP1", package: "swift-nio"),
"SotoUtils",
],
swiftSettings: swiftSettings
),
.target(
name: "SotoUtils",
dependencies: [],
swiftSettings: swiftSettings
),
.target(
name: "SotoTestUtils",
dependencies: [
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoCore/Concurrency/EventStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import NIOCore

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// AsyncSequence of Event stream events
public struct AWSEventStream<Event: Sendable>: Sendable {
let base: AnyAsyncSequence<ByteBuffer>
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoCore/Concurrency/ExpiringValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import Logging

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// Type holding a value and an expiration value.
///
/// When accessing the value you have to provide a closure that will update the
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoCore/Credential/ConfigFileLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import INIParser
import Logging
import NIOCore
import NIOPosix

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// Load settings from AWS credentials and profile configuration files
/// https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html
enum ConfigFileLoader {
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoCore/Encoder/EventStreamDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import NIOCore

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

#if compiler(>=5.10)
internal import SotoXML
#else
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoCore/HTTP/AWSHTTPBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import Logging
import NIOCore
import NIOHTTP1

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// Storage for HTTP body which can be either a ByteBuffer or an AsyncSequence of
/// ByteBuffers
public struct AWSHTTPBody: Sendable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import Logging
import NIOHTTP1

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// Middleware that outputs the contents of requests being sent to AWS and the contents of the responses received.
public struct AWSLoggingMiddleware: AWSMiddlewareProtocol {
@usableFromInline
Expand Down
11 changes: 8 additions & 3 deletions Sources/SotoCore/Middleware/Middleware/S3Middleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
//===----------------------------------------------------------------------===//

import Crypto
import Foundation
@_spi(SotoInternal) import SotoSignerV4

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

#if compiler(>=5.10)
internal import SotoXML
#else
Expand Down Expand Up @@ -114,10 +119,10 @@ public struct S3Middleware: AWSMiddlewareProtocol {
}
}

static let s3PathAllowedCharacters = CharacterSet.urlPathAllowed.subtracting(.init(charactersIn: "+@()&$=:,'!*"))
static let s3PathAllowedCharacters = String.s3PathAllowedCharacters
/// percent encode path value.
private static func urlEncodePath(_ value: String) -> String {
value.addingPercentEncoding(withAllowedCharacters: Self.s3PathAllowedCharacters) ?? value
value.addingPercentEncoding(utf8Buffer: value.utf8, allowedCharacters: Self.s3PathAllowedCharacters)
}

func createBucketFixup(request: inout AWSHTTPRequest, context: AWSMiddlewareContext) {
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoCore/RetryPolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@
//===----------------------------------------------------------------------===//

import AsyncHTTPClient
import Foundation
import NIOCore
import NIOHTTP1
import NIOPosix // Needed for NIOConnectionError

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

/// Creates a RetryPolicy for AWSClient to use
public struct RetryPolicyFactory {
public let retryPolicy: RetryPolicy
Expand Down
15 changes: 14 additions & 1 deletion Sources/SotoCore/Waiters/AWSClient+Waiter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@
//===----------------------------------------------------------------------===//

import Dispatch
import Foundation
import NIOCore

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

#if canImport(Darwin)
import Darwin.C
#elseif canImport(Musl)
import Musl
#elseif canImport(Glibc)
import Glibc
#endif

// MARK: Waiters

extension AWSClient {
Expand Down
45 changes: 19 additions & 26 deletions Sources/SotoSignerV4/signer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
//===----------------------------------------------------------------------===//

import Crypto
import SotoUtils

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import struct Foundation.CharacterSet
import struct Foundation.Data
import struct Foundation.Date
Expand All @@ -22,6 +26,7 @@ import struct Foundation.Locale
import struct Foundation.TimeZone
import struct Foundation.URL
import struct Foundation.URLComponents
#endif

/// Amazon Web Services V4 Signer
public struct AWSSigner: Sendable {
Expand All @@ -34,7 +39,9 @@ public struct AWSSigner: Sendable {

static let hashedEmptyBody = SHA256.hash(data: [UInt8]()).hexDigest()

#if !canImport(FoundationEssentials)
private static let timeStampDateFormatter: DateFormatter = createTimeStampDateFormatter()
#endif

/// Initialise the Signer class with AWS credentials
public init(credentials: Credential, name: String, region: String) {
Expand Down Expand Up @@ -336,7 +343,7 @@ public struct AWSSigner: Sendable {
let canonicalHeaders = signingData.headersToSign
.map { (key: $0.key.lowercased(), value: $0.value) }
.sorted { $0.key < $1.key }
.map { return "\($0.key):\($0.value.trimmingCharacters(in: CharacterSet.whitespaces).removeSequentialWhitespace())" }
.map { return "\($0.key):\($0.value.trimming(while: { $0.isWhitespace }).removeSequentialWhitespace())" }
.joined(separator: "\n")
let canonicalPath: String
let urlComps = URLComponents(url: signingData.unsignedURL, resolvingAgainstBaseURL: false)!
Expand Down Expand Up @@ -399,6 +406,7 @@ public struct AWSSigner: Sendable {
}
}

#if !canImport(FoundationEssentials)
/// create timestamp dateformatter
private static func createTimeStampDateFormatter() -> DateFormatter {
let formatter = DateFormatter()
Expand All @@ -407,11 +415,19 @@ public struct AWSSigner: Sendable {
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}
#endif

#if canImport(FoundationEssentials)
/// return a timestamp formatted for signing requests
static func timestamp(_ date: Date) -> String {
self.timeStampDateFormatter.string(from: date)
date.formatted(Date.ISO8601FormatStyle(dateSeparator: .omitted, timeSeparator: .omitted))
}
#else
/// return a timestamp formatted for signing requests
static func timestamp(_ date: Date) -> String {
timeStampDateFormatter.string(from: date)
}
#endif

/// returns port from URL. If port is set to 80 on an http url or 443 on an https url nil is returned
private static func port(from url: URL) -> Int? {
Expand All @@ -426,29 +442,6 @@ public struct AWSSigner: Sendable {
}
}

extension String {
func queryEncode() -> String {
addingPercentEncoding(withAllowedCharacters: String.queryAllowedCharacters) ?? self
}

func s3PathEncode() -> String {
addingPercentEncoding(withAllowedCharacters: String.s3PathAllowedCharacters) ?? self
}

func uriEncode() -> String {
addingPercentEncoding(withAllowedCharacters: String.uriAllowedCharacters) ?? self
}

func uriEncodeWithSlash() -> String {
addingPercentEncoding(withAllowedCharacters: String.uriAllowedWithSlashCharacters) ?? self
}

static let s3PathAllowedCharacters = CharacterSet.urlPathAllowed.subtracting(.init(charactersIn: "+@()&$=:,'!*"))
static let uriAllowedWithSlashCharacters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~/")
static let uriAllowedCharacters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~")
static let queryAllowedCharacters = CharacterSet(charactersIn: "/;+").inverted
}

@_spi(SotoInternal)
extension Sequence<UInt8> {
/// return a hexEncoded string buffer from an array of bytes
Expand Down Expand Up @@ -485,7 +478,7 @@ extension URL {
}
}

extension String {
extension StringProtocol {
fileprivate func removeSequentialWhitespace() -> String {
reduce(into: "") { result, character in
if result.last?.isWhitespace != true || character.isWhitespace == false {
Expand Down
7 changes: 6 additions & 1 deletion Sources/SotoTestUtils/TestUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@
//===----------------------------------------------------------------------===//

import AsyncHTTPClient
import Foundation
import Logging
import SotoCore
import XCTest

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

@propertyWrapper public struct EnvironmentVariable<Value: LosslessStringConvertible> {
var defaultValue: Value
var variableName: String
Expand Down
Loading
Loading