From 1eee10ae91a859c3117c63971c185f919546e05e Mon Sep 17 00:00:00 2001 From: Mark DiFranco Date: Thu, 14 Nov 2024 12:35:28 -0500 Subject: [PATCH 1/2] Add support for Vapor 4 --- .gitignore | 2 +- .../xcshareddata/xcschemes/S3DemoRun.xcscheme | 100 ----- Package.resolved | 359 +++++++++++------- Package.swift | 55 ++- Sources/S3DemoRun/main.swift | 147 ------- Sources/S3Signer/Extensions/HMAC+Tools.swift | 2 +- .../Extensions/S3Signer+Private.swift | 2 +- Sources/S3Signer/Payload.swift | 2 +- Sources/S3Signer/S3Signer.swift | 2 +- 9 files changed, 259 insertions(+), 412 deletions(-) delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/S3DemoRun.xcscheme delete mode 100644 Sources/S3DemoRun/main.swift diff --git a/.gitignore b/.gitignore index 9661543..f6b72a7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ Packages *.xcodeproj *.xcodeproj/xcshareddata/xcbaselines/4724F8141DA88A530003BAC6.xcbaseline Package.pins - +xcuserdata diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/S3DemoRun.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/S3DemoRun.xcscheme deleted file mode 100644 index 0181475..0000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/S3DemoRun.xcscheme +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Package.resolved b/Package.resolved index 0118a55..f5a8edf 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,133 +1,230 @@ { - "object": { - "pins": [ - { - "package": "async-http-client", - "repositoryURL": "https://github.com/swift-server/async-http-client.git", - "state": { - "branch": null, - "revision": "64851a1a0a2a9e8fa7ae7b3508ce46a1da4a2e1d", - "version": "1.0.0-alpha.2" - } - }, - { - "package": "async-kit", - "repositoryURL": "https://github.com/vapor/async-kit.git", - "state": { - "branch": null, - "revision": "b5742bfbbe2d60f3b77465a0907777261e418f23", - "version": "1.0.0-alpha.1" - } - }, - { - "package": "console-kit", - "repositoryURL": "https://github.com/vapor/console-kit.git", - "state": { - "branch": null, - "revision": "58d000a6236df517e84f162d21afeca757afc2d1", - "version": "4.0.0-alpha.2" - } - }, - { - "package": "HTTPMediaTypes", - "repositoryURL": "https://github.com/Einstore/HTTPMediaTypes.git", - "state": { - "branch": null, - "revision": "cbbb333bce74fbe5ef34648de1d3c2bfef2327fa", - "version": "0.0.1" - } - }, - { - "package": "open-crypto", - "repositoryURL": "https://github.com/vapor/open-crypto.git", - "state": { - "branch": null, - "revision": "06d26edb8e28295bb7103b4f950d5ea58d634c1b", - "version": "4.0.0-alpha.2" - } - }, - { - "package": "routing-kit", - "repositoryURL": "https://github.com/vapor/routing-kit.git", - "state": { - "branch": null, - "revision": "6c7f4b471f9662d05045d82e64e22d5572a16a82", - "version": "4.0.0-alpha.1" - } - }, - { - "package": "swift-log", - "repositoryURL": "https://github.com/apple/swift-log.git", - "state": { - "branch": null, - "revision": "e8aabbe95db22e064ad42f1a4a9f8982664c70ed", - "version": "1.1.1" - } - }, - { - "package": "swift-nio", - "repositoryURL": "https://github.com/apple/swift-nio.git", - "state": { - "branch": null, - "revision": "32760eae40e6b7cb81d4d543bb0a9f548356d9a2", - "version": "2.7.1" - } - }, - { - "package": "swift-nio-extras", - "repositoryURL": "https://github.com/apple/swift-nio-extras.git", - "state": { - "branch": null, - "revision": "66f9a509ed3cc56b6eb367515e421beca4a0af53", - "version": "1.2.0" - } - }, - { - "package": "swift-nio-http2", - "repositoryURL": "https://github.com/apple/swift-nio-http2.git", - "state": { - "branch": null, - "revision": "86ce1dcd0df501401eb1a0d445dbd90aaad84a64", - "version": "1.5.0" - } - }, - { - "package": "swift-nio-ssl", - "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", - "state": { - "branch": null, - "revision": "f5dd7a60ff56f501ff7bf9be753e4b1875bfaf20", - "version": "2.4.0" - } - }, - { - "package": "vapor", - "repositoryURL": "https://github.com/vapor/vapor.git", - "state": { - "branch": null, - "revision": "35f8dc3df0976cff76945a03bfcb763e46a16440", - "version": "4.0.0-alpha.3.1" - } - }, - { - "package": "WebError", - "repositoryURL": "https://github.com/Einstore/WebErrorKit.git", - "state": { - "branch": null, - "revision": "183170b95c46ca5a900d0ea870980c9c280a573a", - "version": "0.0.1" - } - }, - { - "package": "XMLCoding", - "repositoryURL": "https://github.com/LiveUI/XMLCoding.git", - "state": { - "branch": null, - "revision": "8c760e960a5e53a5338c2871c4fcdf06b8c5ace4", - "version": "0.4.0" - } - } - ] - }, - "version": 1 + "pins" : [ + { + "identity" : "async-http-client", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swift-server/async-http-client.git", + "state" : { + "revision" : "0a9b72369b9d87ab155ef585ef50700a34abf070", + "version" : "1.23.1" + } + }, + { + "identity" : "async-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/async-kit.git", + "state" : { + "revision" : "e048c8ee94967e8d8a1c2ec0e1156d6f7fa34d31", + "version" : "1.20.0" + } + }, + { + "identity" : "console-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/console-kit.git", + "state" : { + "revision" : "966d89ae64cd71c652a1e981bc971de59d64f13d", + "version" : "4.15.1" + } + }, + { + "identity" : "httpmediatypes", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Einstore/HTTPMediaTypes.git", + "state" : { + "revision" : "cbbb333bce74fbe5ef34648de1d3c2bfef2327fa", + "version" : "0.0.1" + } + }, + { + "identity" : "multipart-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/multipart-kit.git", + "state" : { + "revision" : "a31236f24bfd2ea2f520a74575881f6731d7ae68", + "version" : "4.7.0" + } + }, + { + "identity" : "routing-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/routing-kit.git", + "state" : { + "revision" : "8c9a227476555c55837e569be71944e02a056b72", + "version" : "4.9.1" + } + }, + { + "identity" : "swift-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-algorithms.git", + "state" : { + "revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-asn1", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-asn1.git", + "state" : { + "revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", + "version" : "1.1.4" + } + }, + { + "identity" : "swift-crypto", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-crypto.git", + "state" : { + "revision" : "06dc63c6d8da54ee11ceb268cde1fa68161afc96", + "version" : "3.9.1" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types", + "state" : { + "revision" : "ef18d829e8b92d731ad27bb81583edd2094d1ce3", + "version" : "1.3.1" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", + "version" : "1.6.1" + } + }, + { + "identity" : "swift-metrics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-metrics.git", + "state" : { + "revision" : "e0165b53d49b413dd987526b641e05e246782685", + "version" : "2.5.0" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "914081701062b11e3bb9e21accc379822621995e", + "version" : "2.76.1" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "2e9746cfc57554f70b650b021b6ae4738abef3e6", + "version" : "1.24.1" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "eaa71bb6ae082eee5a07407b1ad0cbd8f48f9dca", + "version" : "1.34.1" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "c7e95421334b1068490b5d41314a50e70bab23d1", + "version" : "2.29.0" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "bbd5e63cf949b7db0c9edaf7a21e141c52afe214", + "version" : "1.23.0" + } + }, + { + "identity" : "swift-numerics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-numerics.git", + "state" : { + "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b", + "version" : "1.0.2" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "c8a44d836fe7913603e246acab7c528c2e780168", + "version" : "1.4.0" + } + }, + { + "identity" : "vapor", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/vapor.git", + "state" : { + "revision" : "9786a424db75c4e9eb53e255ce1268675b680562", + "version" : "4.106.3" + } + }, + { + "identity" : "weberrorkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Einstore/WebErrorKit.git", + "state" : { + "revision" : "183170b95c46ca5a900d0ea870980c9c280a573a", + "version" : "0.0.1" + } + }, + { + "identity" : "websocket-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/websocket-kit.git", + "state" : { + "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", + "version" : "2.15.0" + } + }, + { + "identity" : "xmlcoding", + "kind" : "remoteSourceControl", + "location" : "https://github.com/LiveUI/XMLCoding.git", + "state" : { + "revision" : "f0fbfe17e73f329e13a6133ff5437f7b174049fd", + "version" : "0.4.1" + } + } + ], + "version" : 2 } diff --git a/Package.swift b/Package.swift index 9f5861b..ae7b7c0 100644 --- a/Package.swift +++ b/Package.swift @@ -1,18 +1,25 @@ -// swift-tools-version:4.0 +// swift-tools-version:5.9 import PackageDescription +import Foundation let package = Package( name: "S3Kit", + platforms: [ + .macOS(.v10_15), + .iOS(.v13), + .tvOS(.v13), + .watchOS(.v6) + ], products: [ .library(name: "S3Kit", targets: ["S3Kit"]), .library(name: "S3Signer", targets: ["S3Signer"]), -// .library(name: "S3TestTools", targets: ["S3TestTools"]) + // .library(name: "S3TestTools", targets: ["S3TestTools"]) ], dependencies: [ .package(url: "https://github.com/apple/swift-nio.git", from: "2.5.0"), - .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-alpha.3"), - .package(url: "https://github.com/vapor/open-crypto.git", from: "4.0.0-alpha.2"), - .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.0.0-alpha.2"), + .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"), + .package(url: "https://github.com/apple/swift-crypto.git", "1.0.0" ..< "4.0.0"), + .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.0.0"), .package(url: "https://github.com/Einstore/HTTPMediaTypes.git", from: "0.0.1"), .package(url: "https://github.com/Einstore/WebErrorKit.git", from: "0.0.1"), .package(url: "https://github.com/LiveUI/XMLCoding.git", from: "0.1.0") @@ -21,43 +28,33 @@ let package = Package( .target( name: "S3Kit", dependencies: [ - "S3Signer", - "AsyncHTTPClient", - "HTTPMediaTypes", - "XMLCoding" + .target(name: "S3Signer"), + .product(name: "AsyncHTTPClient", package: "async-http-client"), + .product(name: "HTTPMediaTypes", package: "HTTPMediaTypes"), + .product(name: "XMLCoding", package: "XMLCoding"), ] ), .target( name: "S3Provider", dependencies: [ - "Vapor", - "S3Kit" + .product(name: "Vapor", package: "vapor"), + .target(name: "S3Kit"), ] ), .target( - name: "S3DemoRun", + name: "S3Signer", dependencies: [ - "Vapor", - "S3Provider" + .product(name: "Crypto", package: "swift-crypto"), + .product(name: "NIOHTTP1", package: "swift-nio"), + .product(name: "HTTPMediaTypes", package: "HTTPMediaTypes"), + .product(name: "WebErrorKit", package: "WebErrorKit"), ] ), - .target( - name: "S3Signer", + .testTarget( + name: "S3Tests", dependencies: [ - "OpenCrypto", - "NIOHTTP1", - "HTTPMediaTypes", - "WebErrorKit" + .target(name: "S3Kit"), ] ), -// .target(name: "S3TestTools", dependencies: [ -// "Vapor", -// "S3Kit" -// ] -// ), - .testTarget(name: "S3Tests", dependencies: [ - "S3Kit" - ] - ) ] ) diff --git a/Sources/S3DemoRun/main.swift b/Sources/S3DemoRun/main.swift deleted file mode 100644 index bea445b..0000000 --- a/Sources/S3DemoRun/main.swift +++ /dev/null @@ -1,147 +0,0 @@ -import Vapor -import S3Provider - - -let DEFAULT_BUCKET = "s3-lib-test.einstore.mgw.cz" - - -func routes(_ router: Routes, _ c: Container) throws { - guard let key = Environment.get("S3_ACCESS_KEY"), let secret = Environment.get("S3_SECRET") else { - fatalError("Missing AWS API key/secret") - } - - let config = S3Signer.Config(accessKey: key, secretKey: secret, region: Region.euCentral1) - let s3: S3Client = try S3(defaultBucket: DEFAULT_BUCKET, config: config) - - // Get all available buckets - router.get("buckets") { req -> EventLoopFuture in - return s3.buckets(on: req.eventLoop) - } - - // Create new bucket - router.put("bucket") { req -> EventLoopFuture in - return s3.create(bucket: "api-created-bucket", region: .euCentral1, on: req.eventLoop).map { - return ":)" - }.recover { error in - if let error = error.s3ErrorMessage() { - return error.message - } - return ":(" - } - } - - // Delete bucket - router.delete("bucket") { req -> EventLoopFuture in - return s3.delete(bucket: "api-created-bucket", region: .euCentral1, on: req.eventLoop).map { - return ":)" - }.recover { error in - if let error = error.s3ErrorMessage() { - return error.message - } - return ":(" - } - } - - // Delete bucket - router.get("files") { req -> EventLoopFuture in - return s3.list(bucket: DEFAULT_BUCKET, region: .euCentral1, headers: [:], on: req.eventLoop).flatMapErrorThrowing { error in - if let error = error.s3ErrorMessage() { - print(error.message) - } - - throw error - } - } - - // Bucket location - router.get("bucket", "location") { req -> EventLoopFuture in - return s3.location(bucket: DEFAULT_BUCKET, on: req.eventLoop).map { region in - return region.hostUrlString() - }.recover { error -> String in - if let error = error as? S3.Error { - switch error { - case .errorResponse(_, let error): - return error.message - default: - return "S3 :(" - } - } - return ":(" - } - } - - // Demonstrate work with files - router.get("files", "test") { req -> EventLoopFuture in - let string = "Content of my example file" - - let fileName = "file-hu.txt" - return s3.put(string: string, destination: fileName, access: .publicRead, on: req.eventLoop).flatMap { putResponse -> EventLoopFuture in - print("PUT response:") - print(putResponse) - return s3.get(file: fileName, on: req.eventLoop).flatMap { getResponse in - print("GET response:") - print(getResponse) - print(String(data: getResponse.data, encoding: .utf8) ?? "Unknown content!") - - return s3.get(fileInfo: fileName, on: req.eventLoop).flatMap { infoResponse in - print("HEAD/Info response:") - print(infoResponse) - - return s3.delete(file: fileName, on: req.eventLoop).flatMapThrowing { response in - print("DELETE response:") - print(response) - let json = try JSONEncoder().encode(infoResponse) - return String(data: json, encoding: .utf8) ?? "Unknown content!" - }.recover { error -> (String) in - if let error = error.s3ErrorMessage() { - return error.message - } - return ":(" - } - } - } - }.recover { error -> (String) in - if let error = error.s3ErrorMessage() { - return error.message - } - return ":(" - } - } -} - -/// Called before your application initializes. -func configure(_ s: inout Services) throws { - /// Register routes - s.extend(Routes.self) { r, c in - try routes(r, c) - } - - /// Register middleware - s.register(MiddlewareConfiguration.self) { c in - // Create _empty_ middleware config - var middlewares = MiddlewareConfiguration() - - // Serves files from `Public/` directory - /// middlewares.use(FileMiddleware.self) - - // Catches errors and converts to HTTP response - try middlewares.use(c.make(ErrorMiddleware.self)) - - return middlewares - } -} - -func boot(_ app: Application) throws { - try LoggingSystem.bootstrap(from: &app.environment) - try app.boot() -} - -public func app(_ environment: Environment) throws -> Application { - let app = Application.init(environment: environment) { s in - try configure(&s) - } - try boot(app) - return app -} - -try app(.detect()).run() diff --git a/Sources/S3Signer/Extensions/HMAC+Tools.swift b/Sources/S3Signer/Extensions/HMAC+Tools.swift index a4c2238..1af5e18 100644 --- a/Sources/S3Signer/Extensions/HMAC+Tools.swift +++ b/Sources/S3Signer/Extensions/HMAC+Tools.swift @@ -1,4 +1,4 @@ -import OpenCrypto +import Crypto extension HMAC { diff --git a/Sources/S3Signer/Extensions/S3Signer+Private.swift b/Sources/S3Signer/Extensions/S3Signer+Private.swift index ee00b5b..e237404 100755 --- a/Sources/S3Signer/Extensions/S3Signer+Private.swift +++ b/Sources/S3Signer/Extensions/S3Signer+Private.swift @@ -1,5 +1,5 @@ import Foundation -import OpenCrypto +import Crypto import NIOHTTP1 import HTTPMediaTypes diff --git a/Sources/S3Signer/Payload.swift b/Sources/S3Signer/Payload.swift index 025e8a2..d3aa889 100755 --- a/Sources/S3Signer/Payload.swift +++ b/Sources/S3Signer/Payload.swift @@ -1,5 +1,5 @@ import Foundation -import OpenCrypto +import Crypto /// Payload object diff --git a/Sources/S3Signer/S3Signer.swift b/Sources/S3Signer/S3Signer.swift index e17e7fd..1caa461 100755 --- a/Sources/S3Signer/S3Signer.swift +++ b/Sources/S3Signer/S3Signer.swift @@ -1,5 +1,5 @@ import Foundation -import OpenCrypto +import Crypto import NIOHTTP1 import WebErrorKit From 47704645024e97e94b428c4ad9b92d7f0a7108a8 Mon Sep 17 00:00:00 2001 From: Mark DiFranco Date: Thu, 14 Nov 2024 17:35:06 -0500 Subject: [PATCH 2/2] Remove reference to URLRequest to play nice with Linux --- Sources/S3Kit/Extensions/S3+Request.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/S3Kit/Extensions/S3+Request.swift b/Sources/S3Kit/Extensions/S3+Request.swift index 4c23d74..cd3c160 100644 --- a/Sources/S3Kit/Extensions/S3+Request.swift +++ b/Sources/S3Kit/Extensions/S3+Request.swift @@ -6,7 +6,13 @@ import AsyncHTTPClient extension S3 { /// Make an S3 request - func make(request url: URL, method: HTTPMethod, headers: HTTPHeaders, data: Data? = nil, cachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, on eventLoop: EventLoop) -> EventLoopFuture { + func make( + request url: URL, + method: HTTPMethod, + headers: HTTPHeaders, + data: Data? = nil, + on eventLoop: EventLoop + ) -> EventLoopFuture { do { let body: HTTPClient.Body? if let data = data {