Extending Vapor Application and Request to support AWS SDK Swift
import AWSS3
import Vapor
public extension Application {
var aws: AWS {
.init(application: self)
}
struct AWS {
struct ClientKey: StorageKey {
typealias Value = AWSClient
}
public var client: AWSClient {
get {
guard let client = self.application.storage[ClientKey.self] else {
fatalError("AWSClient not setup. Use application.aws.client = ...")
}
return client
}
nonmutating set {
self.application.storage.set(ClientKey.self, to: newValue) {
try $0.syncShutdown()
}
}
}
let application: Application
}
}
public extension Request {
var aws: AWS {
.init(request: self)
}
struct AWS {
var client: AWSClient {
return request.application.aws.client
}
let request: Request
}
}
Then in configuration.swift
app.aws.client = AWSClient(httpClientProvider: .shared(app.http.client.shared))
In your controller you can access the AWSClient
as follows
func myRoute(req: Request) -> EventLoopFuture<> {
let client = req.aws.client
let s3 = S3(client: client, region: .useast1)
}
Alternatively you could also include your service structs in the Application
as well.
extension Application.AWS {
struct S3Key: StorageKey {
typealias Value = S3
}
public var s3: S3 {
get {
guard let s3 = self.application.storage[S3Key.self] else {
fatalError("S3 not setup. Use application.aws.s3 = ...")
}
return s3
}
nonmutating set {
self.application.storage[S3Key.self] = newValue
}
}
}
public extension Request.AWS {
var s3: S3 {
return request.application.aws.s3
}
}
Should the
nonmutating set
forclient
maybe do this instead?I found an example in Vapor/APNS which did something similar. Otherwise in all my tests I have to do the following to avoid fatal error warning about shutting down the client.