diff --git a/.gitignore b/.gitignore
index 9661543..c07535b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,7 @@ Packages
*.xcodeproj
*.xcodeproj/xcshareddata/xcbaselines/4724F8141DA88A530003BAC6.xcbaseline
Package.pins
-
+xcuserdata
+DerrivedData/
+.swiftpm
+.env
diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 919434a..0000000
--- a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d9810..0000000
--- a/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/calebkleveter.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/calebkleveter.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index 0100a09..0000000
Binary files a/.swiftpm/xcode/package.xcworkspace/xcuserdata/calebkleveter.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ
diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/pro.xcuserdatad/IDEFindNavigatorScopes.plist b/.swiftpm/xcode/package.xcworkspace/xcuserdata/pro.xcuserdatad/IDEFindNavigatorScopes.plist
deleted file mode 100644
index 5dd5da8..0000000
--- a/.swiftpm/xcode/package.xcworkspace/xcuserdata/pro.xcuserdatad/IDEFindNavigatorScopes.plist
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/pro.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/pro.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index 4aaf760..0000000
Binary files a/.swiftpm/xcode/package.xcworkspace/xcuserdata/pro.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ
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/.swiftpm/xcode/xcshareddata/xcschemes/S3Kit-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/S3Kit-Package.xcscheme
deleted file mode 100644
index c4be616..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/S3Kit-Package.xcscheme
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/S3Kit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/S3Kit.xcscheme
deleted file mode 100644
index f206166..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/S3Kit.xcscheme
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/S3Signer.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/S3Signer.xcscheme
deleted file mode 100644
index 4c63c95..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/S3Signer.xcscheme
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcuserdata/calebkleveter.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/calebkleveter.xcuserdatad/xcschemes/xcschememanagement.plist
deleted file mode 100644
index 5bb8aa3..0000000
--- a/.swiftpm/xcode/xcuserdata/calebkleveter.xcuserdatad/xcschemes/xcschememanagement.plist
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
- SchemeUserState
-
- S3-Package.xcscheme_^#shared#^_
-
- orderHint
- 0
-
- S3.xcscheme_^#shared#^_
-
- orderHint
- 1
-
- S3DemoRun.xcscheme_^#shared#^_
-
- orderHint
- 4
-
- S3Signer.xcscheme_^#shared#^_
-
- orderHint
- 2
-
- S3TestTools.xcscheme_^#shared#^_
-
- orderHint
- 3
-
-
- SuppressBuildableAutocreation
-
- S3
-
- primary
-
-
- S3DemoApp
-
- primary
-
-
- S3DemoRun
-
- primary
-
-
- S3Signer
-
- primary
-
-
- S3TestTools
-
- primary
-
-
- S3Tests
-
- primary
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcuserdata/pro.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/.swiftpm/xcode/xcuserdata/pro.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
deleted file mode 100644
index aa5f7f4..0000000
--- a/.swiftpm/xcode/xcuserdata/pro.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcuserdata/pro.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/pro.xcuserdatad/xcschemes/xcschememanagement.plist
deleted file mode 100644
index 0f43d6c..0000000
--- a/.swiftpm/xcode/xcuserdata/pro.xcuserdatad/xcschemes/xcschememanagement.plist
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
- SchemeUserState
-
- S3DemoRun.xcscheme_^#shared#^_
-
- orderHint
- 3
-
- S3Kit-Package.xcscheme_^#shared#^_
-
- orderHint
- 0
-
- S3Kit.xcscheme_^#shared#^_
-
- orderHint
- 1
-
- S3Signer.xcscheme_^#shared#^_
-
- orderHint
- 2
-
- S3TestTools.xcscheme_^#shared#^_
-
- orderHint
- 3
-
-
- SuppressBuildableAutocreation
-
- S3
-
- primary
-
-
- S3DemoRun
-
- primary
-
-
- S3Kit
-
- primary
-
-
- S3Provider
-
- primary
-
-
- S3Signer
-
- primary
-
-
-
-
-
diff --git a/Package.resolved b/Package.resolved
index 0118a55..c156a44 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/swift-server/async-http-client.git",
"state": {
"branch": null,
- "revision": "64851a1a0a2a9e8fa7ae7b3508ce46a1da4a2e1d",
- "version": "1.0.0-alpha.2"
+ "revision": "e2636a4c24e646d3e480fc666da0c090818beb09",
+ "version": "1.1.0"
}
},
{
@@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/vapor/async-kit.git",
"state": {
"branch": null,
- "revision": "b5742bfbbe2d60f3b77465a0907777261e418f23",
- "version": "1.0.0-alpha.1"
+ "revision": "1f145cffe2109d0fc420bc03b31dacf9de2c7573",
+ "version": "1.0.0"
}
},
{
@@ -24,8 +24,8 @@
"repositoryURL": "https://github.com/vapor/console-kit.git",
"state": {
"branch": null,
- "revision": "58d000a6236df517e84f162d21afeca757afc2d1",
- "version": "4.0.0-alpha.2"
+ "revision": "f674ff0d037346ad5f9a4feb5088b769cdb9e5d3",
+ "version": "4.0.0"
}
},
{
@@ -38,21 +38,30 @@
}
},
{
- "package": "open-crypto",
- "repositoryURL": "https://github.com/vapor/open-crypto.git",
+ "package": "routing-kit",
+ "repositoryURL": "https://github.com/vapor/routing-kit.git",
"state": {
"branch": null,
- "revision": "06d26edb8e28295bb7103b4f950d5ea58d634c1b",
- "version": "4.0.0-alpha.2"
+ "revision": "35da702471cbcc308f58d38aa8fea971fa3fb166",
+ "version": "4.0.0"
}
},
{
- "package": "routing-kit",
- "repositoryURL": "https://github.com/vapor/routing-kit.git",
+ "package": "swift-backtrace",
+ "repositoryURL": "https://github.com/swift-server/swift-backtrace.git",
+ "state": {
+ "branch": null,
+ "revision": "f2fd8c4845a123419c348e0bc4b3839c414077d5",
+ "version": "1.2.0"
+ }
+ },
+ {
+ "package": "swift-crypto",
+ "repositoryURL": "https://github.com/apple/swift-crypto.git",
"state": {
"branch": null,
- "revision": "6c7f4b471f9662d05045d82e64e22d5572a16a82",
- "version": "4.0.0-alpha.1"
+ "revision": "d67ac68d09a95443303e9d6e37b34e7ba101d5f1",
+ "version": "1.0.1"
}
},
{
@@ -60,8 +69,17 @@
"repositoryURL": "https://github.com/apple/swift-log.git",
"state": {
"branch": null,
- "revision": "e8aabbe95db22e064ad42f1a4a9f8982664c70ed",
- "version": "1.1.1"
+ "revision": "74d7b91ceebc85daf387ebb206003f78813f71aa",
+ "version": "1.2.0"
+ }
+ },
+ {
+ "package": "swift-metrics",
+ "repositoryURL": "https://github.com/apple/swift-metrics.git",
+ "state": {
+ "branch": null,
+ "revision": "708b960b4605abb20bc55d65abf6bad607252200",
+ "version": "2.0.0"
}
},
{
@@ -69,8 +87,8 @@
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
- "revision": "32760eae40e6b7cb81d4d543bb0a9f548356d9a2",
- "version": "2.7.1"
+ "revision": "a27a07719ca785bcaca019a5b9fe1814b981b4a2",
+ "version": "2.15.0"
}
},
{
@@ -78,8 +96,8 @@
"repositoryURL": "https://github.com/apple/swift-nio-extras.git",
"state": {
"branch": null,
- "revision": "66f9a509ed3cc56b6eb367515e421beca4a0af53",
- "version": "1.2.0"
+ "revision": "b4dbfacff47fb8d0f9e0a422d8d37935a9f10570",
+ "version": "1.4.0"
}
},
{
@@ -87,8 +105,8 @@
"repositoryURL": "https://github.com/apple/swift-nio-http2.git",
"state": {
"branch": null,
- "revision": "86ce1dcd0df501401eb1a0d445dbd90aaad84a64",
- "version": "1.5.0"
+ "revision": "82eb3fa0974b838358ee46bc6c5381e5ae5de6b9",
+ "version": "1.11.0"
}
},
{
@@ -96,8 +114,8 @@
"repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
"state": {
"branch": null,
- "revision": "f5dd7a60ff56f501ff7bf9be753e4b1875bfaf20",
- "version": "2.4.0"
+ "revision": "ae213938e151964aa691f0e902462fbe06baeeb6",
+ "version": "2.7.1"
}
},
{
@@ -105,8 +123,8 @@
"repositoryURL": "https://github.com/vapor/vapor.git",
"state": {
"branch": null,
- "revision": "35f8dc3df0976cff76945a03bfcb763e46a16440",
- "version": "4.0.0-alpha.3.1"
+ "revision": "ad2aeccfbdd1275c0a8817a8024f0b98d65e3880",
+ "version": "4.0.0-rc.3.12"
}
},
{
@@ -118,13 +136,22 @@
"version": "0.0.1"
}
},
+ {
+ "package": "websocket-kit",
+ "repositoryURL": "https://github.com/vapor/websocket-kit.git",
+ "state": {
+ "branch": null,
+ "revision": "aac462481bcd3039d5db9a0fbe7f4e47eefe2295",
+ "version": "2.0.0-rc.1"
+ }
+ },
{
"package": "XMLCoding",
"repositoryURL": "https://github.com/LiveUI/XMLCoding.git",
"state": {
"branch": null,
- "revision": "8c760e960a5e53a5338c2871c4fcdf06b8c5ace4",
- "version": "0.4.0"
+ "revision": "f0fbfe17e73f329e13a6133ff5437f7b174049fd",
+ "version": "0.4.1"
}
}
]
diff --git a/Package.swift b/Package.swift
index 9f5861b..176eb09 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,62 +1,65 @@
-// swift-tools-version:4.0
+// swift-tools-version:5.2
import PackageDescription
let package = Package(
name: "S3Kit",
+ platforms: [
+ .macOS(.v10_15)
+ ],
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-rc.3.11"),
+ .package(url: "https://github.com/apple/swift-nio.git", from: "2.13.1"),
+ .package(url: "https://github.com/apple/swift-crypto.git", from: "1.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(name: "WebError", url: "https://github.com/Einstore/WebErrorKit.git", from: "0.0.1"),
.package(url: "https://github.com/LiveUI/XMLCoding.git", from: "0.1.0")
],
targets: [
.target(
name: "S3Kit",
dependencies: [
- "S3Signer",
- "AsyncHTTPClient",
- "HTTPMediaTypes",
- "XMLCoding"
+ .target(name: "S3Signer"),
+ .product(name: "AsyncHTTPClient", package: "async-http-client"),
+ .product(name: "XMLCoding", package: "XMLCoding"),
+ .product(name: "HTTPMediaTypes", package: "HTTPMediaTypes")
]
),
.target(
- name: "S3Provider",
+ name: "S3",
dependencies: [
- "Vapor",
- "S3Kit"
+ .target(name: "S3Kit"),
+ .product(name: "Vapor", package: "vapor")
]
),
.target(
name: "S3DemoRun",
dependencies: [
- "Vapor",
- "S3Provider"
+ .target(name: "S3"),
+ .product(name: "Vapor", package: "vapor")
]
),
.target(
name: "S3Signer",
dependencies: [
- "OpenCrypto",
- "NIOHTTP1",
- "HTTPMediaTypes",
- "WebErrorKit"
+ .product(name: "Crypto", package: "swift-crypto"),
+ .product(name: "HTTPMediaTypes", package: "HTTPMediaTypes"),
+ .product(name: "WebErrorKit", package: "WebError"),
+ .product(name: "NIOHTTP1", package: "swift-nio"),
]
),
-// .target(name: "S3TestTools", dependencies: [
-// "Vapor",
-// "S3Kit"
-// ]
-// ),
+ // .target(name: "S3TestTools", dependencies: [
+ // "Vapor",
+ // "S3Kit"
+ // ]
+ // ),
.testTarget(name: "S3Tests", dependencies: [
- "S3Kit"
+ .target(name: "S3Kit")
]
)
]
diff --git a/README.md b/README.md
index 9297b7b..fbeae2c 100644
--- a/README.md
+++ b/README.md
@@ -26,50 +26,30 @@ Update dependencies and targets in Package.swift
```swift
dependencies: [
...
- .package(url: "https://github.com/LiveUI/S3.git", from: "3.0.0-RC3.2"),
+ .package(url: "https://github.com/LiveUI/S3.git", from: "4.0.0-rc.1"),
],
targets: [
- .target(name: "App", dependencies: ["Vapor", "S3"]),
+ .target(name: "App", dependencies: [
+ .package(name: "S3", package: "S3Kit")
+ ],
...
]
```
-Run ```vapor update```
-
-Register S3Client as a service in your configure method
+Configure S3 in your `configure` method:
```swift
-try services.register(s3: S3Signer.Config(...), defaultBucket: "my-bucket")
-```
-
-to use a custom Minio server, use this Config/Region:
-
-```
-S3Signer.Config(accessKey: accessKey,
- secretKey: secretKey,
- region: Region(name: RegionName.usEast1,
- hostName: "127.0.0.1:9000",
- useTLS: false)
+app.s3.configuration = .init(accessKey: "", secretKey: "", region: Region.euNorth1, defaultBucket: "my-bucket")
```
-use S3Client
+Using S3 inside your route handlers
```swift
import S3
-let s3 = try req.makeS3Client() // or req.make(S3Client.self) as? S3
-s3.put(...)
-s3.get(...)
-s3.delete(...)
-```
-
-if you only want to use the signer
-
-```swift
-import S3Signer
-
-let s3 = try req.makeS3Signer() // or req.make(S3Signer.self)
-s3.headers(...)
+app.get("buckets") { req -> EventLoopFuture in
+ req.s3.buckets()
+}
```
### Available methods
@@ -82,178 +62,166 @@ public protocol S3Client: Service {
func buckets(on: Container) -> EventLoopFuture
/// Create a bucket
- func create(bucket: String, region: Region?, on container: Container) -> EventLoopFuture
+ func create(bucket: String, region: Region?) -> EventLoopFuture
/// Delete a bucket
- func delete(bucket: String, region: Region?, on container: Container) -> EventLoopFuture
+ func delete(bucket: String, region: Region?) -> EventLoopFuture
/// Get bucket location
- func location(bucket: String, on container: Container) -> EventLoopFuture
+ func location(bucket: String) -> EventLoopFuture
/// Get list of objects
- func list(bucket: String, region: Region?, on container: Container) -> EventLoopFuture
+ func list(bucket: String, region: Region?) -> EventLoopFuture
/// Get list of objects
- func list(bucket: String, region: Region?, headers: [String: String], on container: Container) -> EventLoopFuture
+ func list(bucket: String, region: Region?, headers: [String: String]) -> EventLoopFuture
/// Upload file to S3
- func put(file: File.Upload, headers: [String: String], on: Container) throws -> EventLoopEventLoopFuture
+ func put(file: File.Upload, headers: [String: String]) throws -> EventLoopEventLoopFuture
/// Upload file to S3
- func put(file url: URL, destination: String, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(file url: URL, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(file url: URL, destination: String, bucket: String?, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(file url: URL, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(file path: String, destination: String, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(file path: String, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(file path: String, destination: String, bucket: String?, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(file path: String, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, destination: String, on: Container) -> EventLoopFuture
+ func put(string: String, destination: String) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, destination: String, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(string: String, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, mime: MediaType, destination: String, on: Container) -> EventLoopFuture
+ func put(string: String, mime: MediaType, destination: String) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, mime: MediaType, destination: String, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(string: String, mime: MediaType, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, mime: MediaType, destination: String, bucket: String?, access: AccessControlList, on: Container) -> EventLoopFuture
+ func put(string: String, mime: MediaType, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture
/// Retrieve file data from S3
- func get(fileInfo file: LocationConvertible, on container: Container) -> EventLoopFuture
+ func get(fileInfo file: LocationConvertible) -> EventLoopFuture
/// Retrieve file data from S3
- func get(fileInfo file: LocationConvertible, headers: [String: String], on container: Container) -> EventLoopFuture
+ func get(fileInfo file: LocationConvertible, headers: [String: String]) -> EventLoopFuture
/// Retrieve file data from S3
- func get(file: LocationConvertible, on: Container) -> EventLoopFuture
+ func get(file: LocationConvertible) -> EventLoopFuture
/// Retrieve file data from S3
- func get(file: LocationConvertible, headers: [String: String], on: Container) -> EventLoopFuture
+ func get(file: LocationConvertible, headers: [String: String]) -> EventLoopFuture
/// Delete file from S3
- func delete(file: LocationConvertible, on: Container) -> EventLoopFuture
+ func delete(file: LocationConvertible) -> EventLoopFuture
/// Delete file from S3
- func delete(file: LocationConvertible, headers: [String: String], on: Container) -> EventLoopFuture
+ func delete(file: LocationConvertible, headers: [String: String]) -> EventLoopFuture
}
```
### Example usage
```swift
-public func routes(_ router: Router) throws {
-
+public func routes(_ app: Application) throws {
// Get all available buckets
- router.get("buckets") { req -> EventLoopFuture in
- let s3 = try req.makeS3Client()
- return try s3.buckets(on: req)
+ app.get("buckets") { req -> EventLoopFuture in
+ req.s3.buckets()
}
// Create new bucket
- router.put("bucket") { req -> EventLoopFuture in
- let s3 = try req.makeS3Client()
- return try s3.create(bucket: "api-created-bucket", region: .euCentral1, on: req).map(to: String.self) {
+ app.put("bucket") { req -> EventLoopFuture in
+ return req.s3.create(bucket: "api-created-bucket", region: .euCentral1).map {
return ":)"
- }.catchMap({ (error) -> (String) in
- if let error = error.s3ErrorMessage() {
- return error.message
- }
- return ":("
- }
- )
- }
-
- // Locate bucket (get region)
- router.get("bucket/location") { req -> EventLoopFuture in
- let s3 = try req.makeS3Client()
- return try s3.location(bucket: "bucket-name", on: req).map(to: String.self) { region in
- return region.hostUrlString()
- }.catchMap({ (error) -> (String) in
- if let error = error as? S3.Error {
- switch error {
- case .errorResponse(_, let error):
- return error.message
- default:
- return "S3 :("
- }
- }
- return ":("
+ }.recover { error in
+ if let error = error.s3ErrorMessage() {
+ return error.message
}
- )
+ return ":("
+ }
}
+
// Delete bucket
- router.delete("bucket") { req -> EventLoopFuture in
- let s3 = try req.makeS3Client()
- return try s3.delete(bucket: "api-created-bucket", region: .euCentral1, on: req).map(to: String.self) {
+ app.delete("bucket") { req -> EventLoopFuture in
+ return req.s3.delete(bucket: "api-created-bucket", region: .euCentral1).map {
return ":)"
- }.catchMap({ (error) -> (String) in
- if let error = error.s3ErrorMessage() {
- return error.message
- }
- return ":("
- }
- )
+ }.recover { error in
+ if let error = error.s3ErrorMessage() {
+ return error.message
+ }
+ return ":("
+ }
}
-
- // Get list of objects
- router.get("files") { req -> EventLoopFuture in
- let s3 = try req.makeS3Client()
- return try s3.list(bucket: "booststore", region: .usEast1, headers: [:], on: req).catchMap({ (error) -> (BucketResults) in
+
+ // List files
+ app.get("files") { req -> EventLoopFuture in
+ return req.s3.list(bucket: DEFAULT_BUCKET, region: .euCentral1, headers: [:]).flatMapErrorThrowing { error in
if let error = error.s3ErrorMessage() {
print(error.message)
}
+
throw error
- })
+ }
}
-
+
+ // Bucket location
+ app.get("bucket", "location") { req -> EventLoopFuture in
+ return req.s3.location(bucket: DEFAULT_BUCKET).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
+ app.get("files", "test") { req -> EventLoopFuture in
let string = "Content of my example file"
-
+
let fileName = "file-hu.txt"
-
- let s3 = try req.makeS3Client()
- do {
- // Upload a file from string
- return try s3.put(string: string, destination: fileName, access: .publicRead, on: req).flatMap(to: String.self) { putResponse in
- print("PUT response:")
- print(putResponse)
- // Get the content of the newly uploaded file
- return try s3.get(file: fileName, on: req).flatMap(to: String.self) { getResponse in
- print("GET response:")
- print(getResponse)
- print(String(data: getResponse.data, encoding: .utf8) ?? "Unknown content!")
- // Get info about the file (HEAD)
- return try s3.get(fileInfo: fileName, on: req).flatMap(to: String.self) { infoResponse in
- print("HEAD/Info response:")
- print(infoResponse)
- // Delete the file
- return try s3.delete(file: fileName, on: req).map() { response in
- print("DELETE response:")
- print(response)
- let json = try JSONEncoder().encode(infoResponse)
- return String(data: json, encoding: .utf8) ?? "Unknown content!"
- }.catchMap({ error -> (String) in
- if let error = error.s3ErrorMessage() {
- return error.message
- }
- return ":("
- }
- )
+ return req.s3.put(string: string, destination: fileName, access: .publicRead).flatMap { putResponse -> EventLoopFuture in
+ print("PUT response:")
+ print(putResponse)
+ return req.s3.get(file: fileName).flatMap { getResponse in
+ print("GET response:")
+ print(getResponse)
+ print(String(data: getResponse.data, encoding: .utf8) ?? "Unknown content!")
+
+ return req.s3.get(fileInfo: fileName).flatMap { infoResponse in
+ print("HEAD/Info response:")
+ print(infoResponse)
+
+ return req.s3.delete(file: fileName).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 ":("
}
}
}
- } catch {
- print(error)
- fatalError()
+ }.recover { error -> (String) in
+ if let error = error.s3ErrorMessage() {
+ return error.message
+ }
+ return ":("
}
}
}
diff --git a/Sources/S3/Application+S3.swift b/Sources/S3/Application+S3.swift
new file mode 100644
index 0000000..b18230f
--- /dev/null
+++ b/Sources/S3/Application+S3.swift
@@ -0,0 +1,23 @@
+import Vapor
+import S3Signer
+
+extension Application {
+ public struct S3 {
+ fileprivate let application: Application
+
+ struct ConfigurationKey: StorageKey {
+ typealias Value = S3Signer.Config
+ }
+
+ public var configuration: S3Signer.Config? {
+ get {
+ application.storage[ConfigurationKey.self]
+ }
+ nonmutating set {
+ application.storage[ConfigurationKey.self] = newValue
+ }
+ }
+ }
+
+ public var s3: S3 { .init(application: self) }
+}
diff --git a/Sources/S3Provider/Exports.swift b/Sources/S3/Exports.swift
similarity index 100%
rename from Sources/S3Provider/Exports.swift
rename to Sources/S3/Exports.swift
diff --git a/Sources/S3Provider/Model/Models+Content.swift b/Sources/S3/Model/Models+Content.swift
similarity index 100%
rename from Sources/S3Provider/Model/Models+Content.swift
rename to Sources/S3/Model/Models+Content.swift
diff --git a/Sources/S3/Request+S3.swift b/Sources/S3/Request+S3.swift
new file mode 100644
index 0000000..e9c4056
--- /dev/null
+++ b/Sources/S3/Request+S3.swift
@@ -0,0 +1,12 @@
+import Vapor
+import S3Kit
+
+extension Request {
+ public var s3: S3 {
+ guard let config = application.s3.configuration else {
+ fatalError("S3 is not configured, please use application.s3.configuration = ...")
+ }
+
+ return .init(config: config, eventLoop: eventLoop, httpClient: application.client.http)
+ }
+}
diff --git a/Sources/S3DemoRun/main.swift b/Sources/S3DemoRun/main.swift
index bea445b..ba213b9 100644
--- a/Sources/S3DemoRun/main.swift
+++ b/Sources/S3DemoRun/main.swift
@@ -1,26 +1,23 @@
import Vapor
-import S3Provider
+import S3
+let DEFAULT_BUCKET = "test-bucket-s3-vapor"
-let DEFAULT_BUCKET = "s3-lib-test.einstore.mgw.cz"
-
-
-func routes(_ router: Routes, _ c: Container) throws {
+func routes(_ app: Application) 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)
+ app.s3.configuration = .init(accessKey: key, secretKey: secret, region: Region.euNorth1, defaultBucket: DEFAULT_BUCKET)
// Get all available buckets
- router.get("buckets") { req -> EventLoopFuture in
- return s3.buckets(on: req.eventLoop)
+ app.get("buckets") { req -> EventLoopFuture in
+ req.s3.buckets()
}
// Create new bucket
- router.put("bucket") { req -> EventLoopFuture in
- return s3.create(bucket: "api-created-bucket", region: .euCentral1, on: req.eventLoop).map {
+ app.put("bucket") { req -> EventLoopFuture in
+ return req.s3.create(bucket: "api-created-bucket", region: .euCentral1).map {
return ":)"
}.recover { error in
if let error = error.s3ErrorMessage() {
@@ -29,10 +26,10 @@ func routes(_ router: Routes, _ c: Container) throws {
return ":("
}
}
-
+
// Delete bucket
- router.delete("bucket") { req -> EventLoopFuture in
- return s3.delete(bucket: "api-created-bucket", region: .euCentral1, on: req.eventLoop).map {
+ app.delete("bucket") { req -> EventLoopFuture in
+ return req.s3.delete(bucket: "api-created-bucket", region: .euCentral1).map {
return ":)"
}.recover { error in
if let error = error.s3ErrorMessage() {
@@ -41,10 +38,10 @@ func routes(_ router: Routes, _ c: Container) throws {
return ":("
}
}
-
- // Delete bucket
- router.get("files") { req -> EventLoopFuture in
- return s3.list(bucket: DEFAULT_BUCKET, region: .euCentral1, headers: [:], on: req.eventLoop).flatMapErrorThrowing { error in
+
+ // List files
+ app.get("files") { req -> EventLoopFuture in
+ return req.s3.list(bucket: DEFAULT_BUCKET, region: .euCentral1, headers: [:]).flatMapErrorThrowing { error in
if let error = error.s3ErrorMessage() {
print(error.message)
}
@@ -52,10 +49,10 @@ func routes(_ router: Routes, _ c: Container) throws {
throw error
}
}
-
+
// Bucket location
- router.get("bucket", "location") { req -> EventLoopFuture in
- return s3.location(bucket: DEFAULT_BUCKET, on: req.eventLoop).map { region in
+ app.get("bucket", "location") { req -> EventLoopFuture in
+ return req.s3.location(bucket: DEFAULT_BUCKET).map { region in
return region.hostUrlString()
}.recover { error -> String in
if let error = error as? S3.Error {
@@ -69,25 +66,25 @@ func routes(_ router: Routes, _ c: Container) throws {
return ":("
}
}
-
+
// Demonstrate work with files
- router.get("files", "test") { req -> EventLoopFuture in
+ app.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
+ return req.s3.put(string: string, destination: fileName, access: .publicRead).flatMap { putResponse -> EventLoopFuture in
print("PUT response:")
print(putResponse)
- return s3.get(file: fileName, on: req.eventLoop).flatMap { getResponse in
+ return req.s3.get(file: fileName).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
+ return req.s3.get(fileInfo: fileName).flatMap { infoResponse in
print("HEAD/Info response:")
print(infoResponse)
- return s3.delete(file: fileName, on: req.eventLoop).flatMapThrowing { response in
+ return req.s3.delete(file: fileName).flatMapThrowing { response in
print("DELETE response:")
print(response)
let json = try JSONEncoder().encode(infoResponse)
@@ -110,38 +107,13 @@ func routes(_ router: Routes, _ c: Container) throws {
}
/// 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
+func configure(_ app: Application) throws {
+ try routes(app)
}
-try app(.detect()).run()
+var env = try Environment.detect()
+try LoggingSystem.bootstrap(from: &env)
+let app = Application(env)
+defer { app.shutdown() }
+try configure(app)
+try app.run()
diff --git a/Sources/S3Kit/Extensions/S3+Bucket.swift b/Sources/S3Kit/Extensions/S3+Bucket.swift
index 47c461e..6934b3b 100644
--- a/Sources/S3Kit/Extensions/S3+Bucket.swift
+++ b/Sources/S3Kit/Extensions/S3+Bucket.swift
@@ -9,7 +9,7 @@ extension S3 {
// MARK: Buckets
/// Get bucket location
- public func location(bucket: String, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func location(bucket: String) -> EventLoopFuture {
let url: URL
let awsHeaders: HTTPHeaders
let region = Region.euWest2
@@ -21,7 +21,7 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .GET, headers: awsHeaders, data: Data(), on: eventLoop).flatMapThrowing { response in
+ return make(request: url, method: .GET, headers: awsHeaders, data: Data()).flatMapThrowing { response in
if response.status == .notFound {
throw Error.notFound
}
@@ -48,7 +48,7 @@ extension S3 {
}
/// Delete bucket
- public func delete(bucket: String, region: Region? = nil, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func delete(bucket: String, region: Region? = nil) -> EventLoopFuture {
let url: URL
let awsHeaders: HTTPHeaders
@@ -59,13 +59,13 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .DELETE, headers: awsHeaders, data: Data(), on: eventLoop).flatMapThrowing(self.check).map { _ in
+ return make(request: url, method: .DELETE, headers: awsHeaders, data: Data()).flatMapThrowing(self.check).map { _ in
return Void()
}
}
/// Create a bucket
- public func create(bucket: String, region: Region? = nil, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func create(bucket: String, region: Region? = nil) -> EventLoopFuture {
let region = region ?? signer.config.region
let content = """
@@ -84,7 +84,7 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .PUT, headers: awsHeaders, data: data, on: eventLoop).flatMapThrowing(self.check).map { _ in
+ return make(request: url, method: .PUT, headers: awsHeaders, data: data).flatMapThrowing(self.check).map { _ in
return Void()
}
}
diff --git a/Sources/S3Kit/Extensions/S3+Copy.swift b/Sources/S3Kit/Extensions/S3+Copy.swift
index dc0200a..270dbf1 100644
--- a/Sources/S3Kit/Extensions/S3+Copy.swift
+++ b/Sources/S3Kit/Extensions/S3+Copy.swift
@@ -8,7 +8,7 @@ extension S3 {
// MARK: Copy
/// Copy file on S3
- public func copy(file: LocationConvertible, to: LocationConvertible, headers strHeaders: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func copy(file: LocationConvertible, to: LocationConvertible, headers strHeaders: [String: String]) -> EventLoopFuture {
do {
let destinationUrl = try makeURLBuilder().url(file: to)
@@ -21,7 +21,7 @@ extension S3 {
payload: .none
)
- return make(request: destinationUrl, method: .PUT, headers: headers, on: eventLoop).flatMapThrowing { response in
+ return make(request: destinationUrl, method: .PUT, headers: headers).flatMapThrowing { response in
return try self.check(response).decode(to: File.CopyResponse.self)
}
} catch let error {
diff --git a/Sources/S3Kit/Extensions/S3+Delete.swift b/Sources/S3Kit/Extensions/S3+Delete.swift
index 8a6df8b..7f90e1e 100644
--- a/Sources/S3Kit/Extensions/S3+Delete.swift
+++ b/Sources/S3Kit/Extensions/S3+Delete.swift
@@ -8,7 +8,7 @@ extension S3 {
// MARK: Delete
/// Delete file from S3
- public func delete(file: LocationConvertible, headers strHeaders: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func delete(file: LocationConvertible, headers strHeaders: [String: String]) -> EventLoopFuture {
let headers: HTTPHeaders
let url: URL
@@ -19,15 +19,15 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .DELETE, headers: headers, data: nil, on: eventLoop).flatMapThrowing(self.check).map { _ in
+ return make(request: url, method: .DELETE, headers: headers, data: nil).flatMapThrowing(self.check).map { _ in
return Void()
}
}
/// Delete file from S3
- public func delete(file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func delete(file: LocationConvertible) -> EventLoopFuture {
return
- delete(file: file, headers: [:], on: eventLoop)
+ delete(file: file, headers: [:])
}
}
diff --git a/Sources/S3Kit/Extensions/S3+Get.swift b/Sources/S3Kit/Extensions/S3+Get.swift
index 3cc2ada..9c64125 100644
--- a/Sources/S3Kit/Extensions/S3+Get.swift
+++ b/Sources/S3Kit/Extensions/S3+Get.swift
@@ -16,7 +16,7 @@ extension S3 {
// MARK: Get
/// Retrieve file data from S3
- public func get(file: LocationConvertible, headers strHeaders: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func get(file: LocationConvertible, headers strHeaders: [String: String]) -> EventLoopFuture {
let url: URL
let headers: HTTPHeaders
@@ -27,7 +27,7 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .GET, headers: headers, on: eventLoop).flatMapThrowing { response in
+ return make(request: url, method: .GET, headers: headers).flatMapThrowing { response in
try self.check(response)
guard var b = response.body, let data = b.readBytes(length: b.readableBytes) else {
@@ -40,8 +40,8 @@ extension S3 {
}
/// Retrieve file data from S3
- public func get(file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture {
- return get(file: file, headers: [:], on: eventLoop)
+ public func get(file: LocationConvertible) -> EventLoopFuture {
+ return get(file: file, headers: [:])
}
}
diff --git a/Sources/S3Kit/Extensions/S3+List.swift b/Sources/S3Kit/Extensions/S3+List.swift
index 07abee5..af913da 100644
--- a/Sources/S3Kit/Extensions/S3+List.swift
+++ b/Sources/S3Kit/Extensions/S3+List.swift
@@ -7,7 +7,7 @@ import NIOHTTP1
extension S3 {
/// Get list of objects
- public func list(bucket: String, region: Region? = nil, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func list(bucket: String, region: Region? = nil, headers: [String: String]) -> EventLoopFuture {
let region = region ?? signer.config.region
guard let baseUrl = URL(string: region.hostUrlString(bucket: bucket)), let host = baseUrl.host,
var components = URLComponents(string: baseUrl.absoluteString) else {
@@ -30,15 +30,15 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .GET, headers: awsHeaders, data: Data(), on: eventLoop).flatMapThrowing { response in
+ return make(request: url, method: .GET, headers: awsHeaders, data: Data()).flatMapThrowing { response in
try self.check(response)
return try response.decode(to: BucketResults.self)
}
}
/// Get list of objects
- public func list(bucket: String, region: Region? = nil, on eventLoop: EventLoop) -> EventLoopFuture {
- return list(bucket: bucket, region: region, headers: [:], on: eventLoop)
+ public func list(bucket: String, region: Region? = nil) -> EventLoopFuture {
+ return list(bucket: bucket, region: region, headers: [:])
}
}
diff --git a/Sources/S3Kit/Extensions/S3+Move.swift b/Sources/S3Kit/Extensions/S3+Move.swift
index 3801b02..b626364 100644
--- a/Sources/S3Kit/Extensions/S3+Move.swift
+++ b/Sources/S3Kit/Extensions/S3+Move.swift
@@ -7,9 +7,9 @@ extension S3 {
// MARK: Move
/// Copy file on S3
- public func move(file: LocationConvertible, to destination: LocationConvertible, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
- return copy(file: file, to: destination, headers: headers, on: eventLoop).flatMap { copyResult in
- return self.delete(file: file, on: eventLoop).map { _ in
+ public func move(file: LocationConvertible, to destination: LocationConvertible, headers: [String: String]) -> EventLoopFuture {
+ return copy(file: file, to: destination, headers: headers).flatMap { copyResult in
+ return self.delete(file: file).map { _ in
return copyResult
}
}
diff --git a/Sources/S3Kit/Extensions/S3+ObjectInfo.swift b/Sources/S3Kit/Extensions/S3+ObjectInfo.swift
index 1b9f91f..aa36b62 100644
--- a/Sources/S3Kit/Extensions/S3+ObjectInfo.swift
+++ b/Sources/S3Kit/Extensions/S3+ObjectInfo.swift
@@ -9,19 +9,19 @@ extension S3 {
/// Get acl file information (ACL)
/// https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html
- public func get(acl file: LocationConvertible, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func get(acl file: LocationConvertible, headers: [String: String]) -> EventLoopFuture {
fatalError("Not implemented")
}
/// Get acl file information
/// https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html
- func get(acl file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture {
- return get(fileInfo: file, headers: [:], on: eventLoop)
+ func get(acl file: LocationConvertible) -> EventLoopFuture {
+ return get(fileInfo: file, headers: [:])
}
/// Get file information (HEAD)
/// https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html
- public func get(fileInfo file: LocationConvertible, headers strHeaders: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func get(fileInfo file: LocationConvertible, headers strHeaders: [String: String]) -> EventLoopFuture {
let url: URL
let headers: HTTPHeaders
@@ -32,7 +32,7 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .HEAD, headers: headers, data: Data(), on: eventLoop).flatMapThrowing { response in
+ return make(request: url, method: .HEAD, headers: headers, data: Data()).flatMapThrowing { response in
try self.check(response)
let bucket = file.bucket ?? self.defaultBucket
@@ -54,8 +54,8 @@ extension S3 {
/// Get file information (HEAD)
/// https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html
- public func get(fileInfo file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture {
- return get(fileInfo: file, headers: [:], on: eventLoop)
+ public func get(fileInfo file: LocationConvertible) -> EventLoopFuture {
+ return get(fileInfo: file, headers: [:])
}
}
diff --git a/Sources/S3Kit/Extensions/S3+Put.swift b/Sources/S3Kit/Extensions/S3+Put.swift
index 4875e16..6948d19 100755
--- a/Sources/S3Kit/Extensions/S3+Put.swift
+++ b/Sources/S3Kit/Extensions/S3+Put.swift
@@ -7,7 +7,7 @@ extension S3 {
// MARK: Upload
/// Upload file to S3
- public func put(file: File.Upload, headers strHeaders: [String: String], on eventLoop: EventLoop) -> EventLoopFuture {
+ public func put(file: File.Upload, headers strHeaders: [String: String]) -> EventLoopFuture {
let headers: HTTPHeaders
let url: URL
@@ -27,7 +27,7 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .PUT, headers: headers, data: file.data, on: eventLoop).flatMapThrowing { response in
+ return make(request: url, method: .PUT, headers: headers, data: file.data).flatMapThrowing { response in
try self.check(response)
let res = File.Response(data: file.data, bucket: file.bucket ?? self.defaultBucket, path: file.path, access: file.access, mime: file.mime)
return res
@@ -35,12 +35,12 @@ extension S3 {
}
/// Upload file to S3
- public func put(file: File.Upload, on eventLoop: EventLoop) -> EventLoopFuture {
- return put(file: file, headers: [:], on: eventLoop)
+ public func put(file: File.Upload) -> EventLoopFuture {
+ return put(file: file, headers: [:])
}
/// Upload file by it's URL to S3
- public func put(file url: URL, destination: String, access: AccessControlList = .privateAccess, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func put(file url: URL, destination: String, access: AccessControlList = .privateAccess) -> EventLoopFuture {
let data: Data
do {
data = try Data(contentsOf: url)
@@ -49,17 +49,17 @@ extension S3 {
}
let file = File.Upload(data: data, bucket: nil, destination: destination, access: access, mime: mimeType(forFileAtUrl: url))
- return put(file: file, on: eventLoop)
+ return put(file: file)
}
/// Upload file by it's path to S3
- public func put(file path: String, destination: String, access: AccessControlList = .privateAccess, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func put(file path: String, destination: String, access: AccessControlList = .privateAccess) -> EventLoopFuture {
let url: URL = URL(fileURLWithPath: path)
- return put(file: url, destination: destination, bucket: nil, access: access, on: eventLoop)
+ return put(file: url, destination: destination, bucket: nil, access: access)
}
/// Upload file by it's URL to S3, full set
- public func put(file url: URL, destination: String, bucket: String?, access: AccessControlList = .privateAccess, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func put(file url: URL, destination: String, bucket: String?, access: AccessControlList = .privateAccess) -> EventLoopFuture {
let data: Data
do {
data = try Data(contentsOf: url)
@@ -68,13 +68,13 @@ extension S3 {
}
let file = File.Upload(data: data, bucket: bucket, destination: destination, access: access, mime: mimeType(forFileAtUrl: url))
- return put(file: file, on: eventLoop)
+ return put(file: file)
}
/// Upload file by it's path to S3, full set
- public func put(file path: String, destination: String, bucket: String?, access: AccessControlList = .privateAccess, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func put(file path: String, destination: String, bucket: String?, access: AccessControlList = .privateAccess) -> EventLoopFuture {
let url: URL = URL(fileURLWithPath: path)
- return put(file: url, destination: destination, bucket: bucket, access: access, on: eventLoop)
+ return put(file: url, destination: destination, bucket: bucket, access: access)
}
}
diff --git a/Sources/S3Kit/Extensions/S3+Request.swift b/Sources/S3Kit/Extensions/S3+Request.swift
index 4c23d74..34f00f4 100644
--- a/Sources/S3Kit/Extensions/S3+Request.swift
+++ b/Sources/S3Kit/Extensions/S3+Request.swift
@@ -6,7 +6,7 @@ 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, cachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy) -> EventLoopFuture {
do {
let body: HTTPClient.Body?
if let data = data {
@@ -27,8 +27,8 @@ extension S3 {
headers: headers,
body: body
)
- let client = HTTPClient(eventLoopGroupProvider: .shared(eventLoop))
- return client.execute(request: request)
+
+ return httpClient.execute(request: request, eventLoop: .delegate(on: eventLoop))
} catch {
return eventLoop.makeFailedFuture(error)
}
diff --git a/Sources/S3Kit/Extensions/S3+Service.swift b/Sources/S3Kit/Extensions/S3+Service.swift
index e7d72a9..6b74536 100644
--- a/Sources/S3Kit/Extensions/S3+Service.swift
+++ b/Sources/S3Kit/Extensions/S3+Service.swift
@@ -7,7 +7,7 @@ extension S3 {
// MARK: Buckets
/// Get list of buckets
- public func buckets(on eventLoop: EventLoop) -> EventLoopFuture {
+ public func buckets() -> EventLoopFuture {
let headers: HTTPHeaders
let url: URL
@@ -18,7 +18,7 @@ extension S3 {
return eventLoop.makeFailedFuture(error)
}
- return make(request: url, method: .GET, headers: headers, data: Data(), on: eventLoop).flatMapThrowing { response in
+ return make(request: url, method: .GET, headers: headers, data: Data()).flatMapThrowing { response in
try self.check(response)
return try response.decode(to: BucketsInfo.self)
}
diff --git a/Sources/S3Kit/Extensions/S3+Strings.swift b/Sources/S3Kit/Extensions/S3+Strings.swift
index ea70679..ecba9c5 100755
--- a/Sources/S3Kit/Extensions/S3+Strings.swift
+++ b/Sources/S3Kit/Extensions/S3+Strings.swift
@@ -5,32 +5,32 @@ import HTTPMediaTypes
extension S3 {
/// Upload file content to S3, full set
- public func put(string: String, mime: HTTPMediaType, destination: String, bucket: String?, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture {
+ public func put(string: String, mime: HTTPMediaType, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture {
guard let data: Data = string.data(using: String.Encoding.utf8) else {
return eventLoop.makeFailedFuture(Error.badStringData)
}
let file = File.Upload(data: data, bucket: bucket, destination: destination, access: access, mime: mime.description)
- return put(file: file, on: eventLoop)
+ return put(file: file)
}
/// Upload file content to S3
- public func put(string: String, mime: HTTPMediaType, destination: String, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture {
- return put(string: string, mime: mime, destination: destination, bucket: nil, access: access, on: eventLoop)
+ public func put(string: String, mime: HTTPMediaType, destination: String, access: AccessControlList) -> EventLoopFuture {
+ return put(string: string, mime: mime, destination: destination, bucket: nil, access: access)
}
/// Upload file content to S3
- public func put(string: String, destination: String, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture {
- return put(string: string, mime: .plainText, destination: destination, bucket: nil, access: access, on: eventLoop)
+ public func put(string: String, destination: String, access: AccessControlList) -> EventLoopFuture {
+ return put(string: string, mime: .plainText, destination: destination, bucket: nil, access: access)
}
/// Upload file content to S3
- public func put(string: String, mime: HTTPMediaType, destination: String, on eventLoop: EventLoop) -> EventLoopFuture {
- return put(string: string, mime: mime, destination: destination, access: .privateAccess, on: eventLoop)
+ public func put(string: String, mime: HTTPMediaType, destination: String) -> EventLoopFuture {
+ return put(string: string, mime: mime, destination: destination, access: .privateAccess)
}
/// Upload file content to S3
- public func put(string: String, destination: String, on eventLoop: EventLoop) -> EventLoopFuture {
- return put(string: string, mime: .plainText, destination: destination, bucket: nil, access: .privateAccess, on: eventLoop)
+ public func put(string: String, destination: String) -> EventLoopFuture {
+ return put(string: string, mime: .plainText, destination: destination, bucket: nil, access: .privateAccess)
}
}
diff --git a/Sources/S3Kit/Extensions/String+Tools.swift b/Sources/S3Kit/Extensions/String+Tools.swift
index 83195b0..fd54f4a 100644
--- a/Sources/S3Kit/Extensions/String+Tools.swift
+++ b/Sources/S3Kit/Extensions/String+Tools.swift
@@ -11,5 +11,4 @@ extension String {
}
var bytes: [UInt8] { .init(utf8) }
-
}
diff --git a/Sources/S3Kit/Protocols/S3Client.swift b/Sources/S3Kit/Protocols/S3Client.swift
index 4cf4645..9787fd1 100644
--- a/Sources/S3Kit/Protocols/S3Client.swift
+++ b/Sources/S3Kit/Protocols/S3Client.swift
@@ -4,97 +4,96 @@ import HTTPMediaTypes
/// S3 client Protocol
-public protocol S3Client {
-
+public protocol S3Client {
/// Get list of objects
- func buckets(on eventLoop: EventLoop) -> EventLoopFuture
+ func buckets() -> EventLoopFuture
/// Create a bucket
- func create(bucket: String, region: Region?, on eventLoop: EventLoop) -> EventLoopFuture
+ func create(bucket: String, region: Region?) -> EventLoopFuture
/// Delete a bucket wherever it is
// func delete(bucket: String, on container: Container) -> EventLoopFuture
/// Delete a bucket
- func delete(bucket: String, region: Region?, on eventLoop: EventLoop) -> EventLoopFuture
+ func delete(bucket: String, region: Region?) -> EventLoopFuture
/// Get bucket location
- func location(bucket: String, on eventLoop: EventLoop) -> EventLoopFuture
+ func location(bucket: String) -> EventLoopFuture
/// Get list of objects
- func list(bucket: String, region: Region?, on eventLoop: EventLoop) -> EventLoopFuture
+ func list(bucket: String, region: Region?) -> EventLoopFuture
/// Get list of objects
- func list(bucket: String, region: Region?, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture
+ func list(bucket: String, region: Region?, headers: [String: String]) -> EventLoopFuture
/// Upload file to S3
- func put(file: File.Upload, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(file: File.Upload) -> EventLoopFuture
/// Upload file to S3
- func put(file: File.Upload, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture
+ func put(file: File.Upload, headers: [String: String]) -> EventLoopFuture
/// Upload file to S3
- func put(file url: URL, destination: String, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(file url: URL, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(file url: URL, destination: String, bucket: String?, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(file url: URL, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(file path: String, destination: String, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(file path: String, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(file path: String, destination: String, bucket: String?, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(file path: String, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, destination: String, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(string: String, destination: String) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, destination: String, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(string: String, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, mime: HTTPMediaType, destination: String, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(string: String, mime: HTTPMediaType, destination: String) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, mime: HTTPMediaType, destination: String, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(string: String, mime: HTTPMediaType, destination: String, access: AccessControlList) -> EventLoopFuture
/// Upload file to S3
- func put(string: String, mime: HTTPMediaType, destination: String, bucket: String?, access: AccessControlList, on eventLoop: EventLoop) -> EventLoopFuture
+ func put(string: String, mime: HTTPMediaType, destination: String, bucket: String?, access: AccessControlList) -> EventLoopFuture
/// File URL
func url(fileInfo file: LocationConvertible) throws -> URL
/// Retrieve file data from S3
- func get(fileInfo file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture
+ func get(fileInfo file: LocationConvertible) -> EventLoopFuture
/// Retrieve file data from S3
- func get(fileInfo file: LocationConvertible, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture
+ func get(fileInfo file: LocationConvertible, headers: [String: String]) -> EventLoopFuture
/// Retrieve file data from S3
- func get(file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture
+ func get(file: LocationConvertible) -> EventLoopFuture
/// Retrieve file data from S3
- func get(file: LocationConvertible, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture
+ func get(file: LocationConvertible, headers: [String: String]) -> EventLoopFuture
/// Delete file from S3
- func delete(file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture
+ func delete(file: LocationConvertible) -> EventLoopFuture
/// Delete file from S3
- func delete(file: LocationConvertible, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture
+ func delete(file: LocationConvertible, headers: [String: String]) -> EventLoopFuture
/// Copy file on S3
- func copy(file: LocationConvertible, to: LocationConvertible, headers: [String: String], on eventLoop: EventLoop) -> EventLoopFuture
+ func copy(file: LocationConvertible, to: LocationConvertible, headers: [String: String]) -> EventLoopFuture
}
extension S3Client {
/// Retrieve file data from S3
- func get(file: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture {
- return get(file: file, headers: [:], on: eventLoop)
+ func get(file: LocationConvertible) -> EventLoopFuture {
+ return get(file: file, headers: [:])
}
/// Copy file on S3
- public func copy(file: LocationConvertible, to: LocationConvertible, on eventLoop: EventLoop) -> EventLoopFuture {
- return self.copy(file: file, to: to, headers: [:], on: eventLoop)
+ public func copy(file: LocationConvertible, to: LocationConvertible) -> EventLoopFuture {
+ return self.copy(file: file, to: to, headers: [:])
}
static var dateFormatter: DateFormatter {
diff --git a/Sources/S3Kit/S3.swift b/Sources/S3Kit/S3.swift
index a485f73..afbe8ae 100755
--- a/Sources/S3Kit/S3.swift
+++ b/Sources/S3Kit/S3.swift
@@ -6,6 +6,8 @@ import AsyncHTTPClient
/// Main S3 class
public class S3: S3Client {
+ public let eventLoop: EventLoop
+ public let httpClient: HTTPClient
/// Error messages
public enum Error: Swift.Error {
@@ -30,23 +32,27 @@ public class S3: S3Client {
// MARK: Initialization
/// Basic initialization method, also registers S3Signer and self with services
- @discardableResult public convenience init(defaultBucket: String, config: S3Signer.Config) throws {
- let signer = try S3Signer(config)
- try self.init(defaultBucket: defaultBucket, signer: signer)
+ public convenience init(config: S3Signer.Config, eventLoop: EventLoop, httpClient: HTTPClient) {
+ let signer = S3Signer(config)
+ self.init(defaultBucket: config.defaultBucket, signer: signer, eventLoop: eventLoop, httpClient: httpClient)
}
/// Basic initialization method
- public init(defaultBucket: String, signer: S3Signer) throws {
+ public init(defaultBucket: String, signer: S3Signer, eventLoop: EventLoop, httpClient: HTTPClient) {
self.defaultBucket = defaultBucket
self.signer = signer
self.urlBuilder = nil
+ self.eventLoop = eventLoop
+ self.httpClient = httpClient
}
/// Basic initialization method
- public init(urlBuilder: URLBuilder, defaultBucket: String, signer: S3Signer) throws {
+ public init(urlBuilder: URLBuilder, defaultBucket: String, signer: S3Signer, eventLoop: EventLoop, httpClient: HTTPClient) {
self.defaultBucket = defaultBucket
self.signer = signer
self.urlBuilder = nil
+ self.eventLoop = eventLoop
+ self.httpClient = httpClient
}
}
diff --git a/Sources/S3Signer/Extensions/Data+Hex.swift b/Sources/S3Signer/Extensions/Data+Hex.swift
new file mode 100644
index 0000000..433ddd9
--- /dev/null
+++ b/Sources/S3Signer/Extensions/Data+Hex.swift
@@ -0,0 +1,5 @@
+extension Data {
+ var hexString: String {
+ return self.reduce("", { $0 + String(format: "%02x", $1) })
+ }
+}
diff --git a/Sources/S3Signer/Extensions/HMAC+Tools.swift b/Sources/S3Signer/Extensions/HMAC+Tools.swift
index a4c2238..1438842 100644
--- a/Sources/S3Signer/Extensions/HMAC+Tools.swift
+++ b/Sources/S3Signer/Extensions/HMAC+Tools.swift
@@ -1,5 +1,4 @@
-import OpenCrypto
-
+import Crypto
extension HMAC {
@@ -26,5 +25,4 @@ extension HashedAuthenticationCode {
var data: Data {
return Data(self)
}
-
}
diff --git a/Sources/S3Signer/Extensions/S3Signer+Private.swift b/Sources/S3Signer/Extensions/S3Signer+Private.swift
index ee00b5b..b7d5d2d 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
@@ -55,11 +55,11 @@ extension S3Signer {
let dateRegionServiceKey = HMAC.signature(config.service, key: dateRegionKey)
let signingKey = HMAC.signature("aws4_request", key: dateRegionServiceKey)
let signature = HMAC.signature(stringToSign, key: signingKey)
- return signature.description
+ return Data(signature).hexString
}
func createStringToSign(_ canonicalRequest: String, dates: Dates, region: Region) throws -> String {
- let canonRequestHash = SHA256.hash(data: canonicalRequest.bytes).description
+ let canonRequestHash = Data(SHA256.hash(data: canonicalRequest.bytes)).hexString
let components = [
"AWS4-HMAC-SHA256",
dates.long,
diff --git a/Sources/S3Signer/Payload.swift b/Sources/S3Signer/Payload.swift
index 025e8a2..cca390c 100755
--- a/Sources/S3Signer/Payload.swift
+++ b/Sources/S3Signer/Payload.swift
@@ -1,5 +1,5 @@
import Foundation
-import OpenCrypto
+import Crypto
/// Payload object
@@ -30,9 +30,9 @@ extension Payload {
func hashed() -> String {
switch self {
case .bytes(let bytes):
- return SHA256.hash(data: [UInt8](bytes)).description
+ return Data(SHA256.hash(data: [UInt8](bytes))).hexString
case .none:
- return SHA256.hash(data: []).description
+ return Data(SHA256.hash(data: [])).hexString
case .unsigned:
return "UNSIGNED-PAYLOAD"
}
diff --git a/Sources/S3Signer/Region.swift b/Sources/S3Signer/Region.swift
index 596235b..a45e6b8 100755
--- a/Sources/S3Signer/Region.swift
+++ b/Sources/S3Signer/Region.swift
@@ -32,6 +32,9 @@ public struct Region {
/// EU (Frankfurt)
public static let euCentral1: Name = "eu-central-1"
+ /// EU (Stockholm)
+ public static let euNorth1: Name = "eu-north-1"
+
/// EU (Ireland)
public static let euWest1: Name = "eu-west-1"
@@ -124,6 +127,9 @@ extension Region {
/// convenience var for EU (Frankfurt)
public static let euCentral1 = Region(name: .euCentral1)
+ /// EU (Stockholm)
+ public static let euNorth1 = Region(name: .euNorth1)
+
/// convenience var for EU (Ireland)
public static let euWest1 = Region(name: .euWest1)
diff --git a/Sources/S3Signer/S3Signer.swift b/Sources/S3Signer/S3Signer.swift
index e17e7fd..fe8ff98 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
@@ -65,6 +65,9 @@ public final class S3Signer {
/// AWS Service type
let service: String = "s3"
+ /// Default bucket name
+ public let defaultBucket: String
+
/// Initalizer
/// - Parameter accessKey: S3 access token
@@ -72,12 +75,13 @@ public final class S3Signer {
/// - Parameter region: Region
/// - Parameter version: Signing version
/// - Parameter securityToken: Temporary security token
- public init(accessKey: String, secretKey: String, region: Region, version: Version = .v4, securityToken: String? = nil) {
+ public init(accessKey: String, secretKey: String, region: Region, version: Version = .v4, securityToken: String? = nil, defaultBucket: String) {
self.accessKey = accessKey
self.secretKey = secretKey
self.region = region
self.securityToken = securityToken
self.authVersion = version
+ self.defaultBucket = defaultBucket
}
}
@@ -86,7 +90,7 @@ public final class S3Signer {
public private(set) var config: Config
/// Initializer
- public init(_ config: Config) throws {
+ public init(_ config: Config) {
self.config = config
}
diff --git a/Tests/S3Tests/BaseTestCase.swift b/Tests/S3Tests/BaseTestCase.swift
index bfb7b10..cbc1d0b 100644
--- a/Tests/S3Tests/BaseTestCase.swift
+++ b/Tests/S3Tests/BaseTestCase.swift
@@ -14,12 +14,12 @@ class BaseTestCase: XCTestCase {
override func setUp() {
super.setUp()
region = Region.usEast1
- signer = try! S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region))
+ signer = try! S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region, defaultBucket: ""))
// this is the "seconds" representation of "20130524T000000Z"
overridenDate = Dates(Date(timeIntervalSince1970: (60*60*24) * 15849))
- if let s = try? S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region)) {
+ if let s = try? S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region, defaultBucket: "")) {
signer = s
} else {
XCTFail("Could not intialize signer")
diff --git a/Tests/S3Tests/S3SignerV2Tests.swift b/Tests/S3Tests/S3SignerV2Tests.swift
index 96f5fd0..e1d6c67 100644
--- a/Tests/S3Tests/S3SignerV2Tests.swift
+++ b/Tests/S3Tests/S3SignerV2Tests.swift
@@ -5,12 +5,7 @@ import XCTest
class S3SignerV2Tests: BaseTestCase {
override func setUp() {
super.setUp()
- signer = try! S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region, version: .v2))
- if let s = try? S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region, version: .v2)) {
- signer = s
- } else {
- XCTFail("Could not intialize signer")
- }
+ signer = S3Signer(S3Signer.Config(accessKey: accessKey, secretKey: secretKey, region: region, version: .v2, defaultBucket: ""))
}
// TOOD: appropriate testing would try various cases (where URL has signable query items, etc)