Skip to content
This repository has been archived by the owner on Apr 20, 2024. It is now read-only.

Commit

Permalink
Basic S3 support.
Browse files Browse the repository at this point in the history
  • Loading branch information
BrettRToomey committed Dec 30, 2016
1 parent ffbc2bf commit b5d99a3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 37 deletions.
6 changes: 3 additions & 3 deletions Sources/Driver/Authentication/PercentEncoder.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import Core

extension Byte {
static let awsQueryAllowed = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~=".bytes
public static let awsQueryAllowed = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~=".bytes

static let awsPathAllowed = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~/".bytes
public static let awsPathAllowed = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~/".bytes
}

extension String {
func percentEncode(allowing allowed: Bytes) throws -> String {
public func percentEncode(allowing allowed: Bytes) throws -> String {
let bytes = self.bytes
let encodedBytes = try percentEncodedUppercase(bytes, shouldEncode: {
return !allowed.contains($0)
Expand Down
81 changes: 47 additions & 34 deletions Sources/S3/S3.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,73 @@ import Driver
import Transport

public struct S3 {
let signer: AWSSignatureV4?
let bucket: String
let isVirtualHosted: Bool
public enum Error: Swift.Error {
case unimplemented
case invalidResponse(Status, String?)
}

let signer: AWSSignatureV4
public var host: String

public init(
host: String,
accessKey: String,
secretKey: String,
region: Region,
bucket: String,
isBucketVirtualHosted: Bool = false
region: Region
) {
signer = nil
self.bucket = bucket
self.isVirtualHosted = isBucketVirtualHosted
self.host = host
signer = AWSSignatureV4(
service: "s3",
host: host,
region: region,
accessKey: accessKey,
secretKey: secretKey
)
}

public func upload(bytes: Bytes, path: String, access: AccessControlList) throws {
let url = generateURL(for: path)
let headers = try signer.sign(
payload: .bytes(bytes),
method: .put,
path: path
//TODO(Brett): headers & AccessControlList
)

let response = try BasicClient.put(url, headers: headers, body: Body.data(bytes))
guard response.status == .ok else {
throw Error.invalidResponse(response.status, response.body.bytes?.string)
}
}

public func get(path: String) throws -> Response {
public func get(path: String) throws -> Bytes {
let url = generateURL(for: path)
let headers = try signer.sign(path: path)

/*
let headers = try s3Signer.authHeaderV4(
httpMethod: .get,
urlString: url,
headers: [:],
payload: .none
).vaporHeaders
*/
let response = try BasicClient.get(url, headers: headers)
guard response.status == .ok else {
throw Error.invalidResponse(response.status, response.body.bytes?.string)
}

return try BasicClient.get(url, headers: [:])
}

public func exist(file: String) {

guard let bytes = response.body.bytes else {
throw Error.invalidResponse(
.internalServerError,
"Response from S3 did not contain a body."
)
}

return bytes
}

public func delete(file: String) {

public func delete(file: String) throws {
throw Error.unimplemented
}
}

extension S3 {
func generateURL(for path: String) -> String {
var url: String

if isVirtualHosted {
url = "https://\(bucket).s3.amazonaws.com/"
} else {
url = "https://s3.amazonaws.com/\(bucket)/"
}

return url + path
//FIXME(Brett):
return "https://\(host)\(path)"
}
}

Expand Down
1 change: 1 addition & 0 deletions Tests/AWSTests/AWSTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import XCTest
import HTTP
import Transport
@testable import S3
@testable import Driver

class AWSTests: XCTestCase {
Expand Down

0 comments on commit b5d99a3

Please sign in to comment.