Skip to content

Commit

Permalink
Clean up the project a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonycastelli committed Apr 24, 2018
1 parent 992cac0 commit df99d74
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 14 deletions.
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions Sources/S3Storage/S3 Signer/Payload.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Payload.swift
// S3Storage
//
// Created by Anthony Castelli on 4/23/18.
//

import Foundation
import Vapor
import Crypto

public enum Payload {
case bytes(Data)
case none
case unsigned
}

extension Payload {
internal func hashed() throws -> String {
switch self {
case .bytes(let bytes): return try SHA256.hash(bytes).hexEncodedString()
case .none: return try SHA256.hash("".convertToData()).hexEncodedString()
case .unsigned: return "UNSIGNED-PAYLOAD"
}
}

internal var bytes: Data {
switch self {
case .bytes(let bytes): return bytes
default: return "".convertToData()
}
}

internal var isBytes: Bool {
switch self {
case .bytes( _), .none: return true
default: return false
}
}

internal var size: String {
switch self {
case .bytes, .none: return self.bytes.count.description
case .unsigned: return "UNSIGNED-PAYLOAD"
}
}

internal var isUnsigned: Bool {
switch self {
case .unsigned: return true
default: return false
}
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,33 @@ import HTTP
import Crypto

extension S3Adapter {
public func generateAuthHeader(_ httpMethod: HTTPMethod, urlString: String, headers: [String: String] = [:], payload: Data?) throws -> HTTPHeaders {
internal func generateAuthHeader(_ httpMethod: HTTPMethod, urlString: String, headers: [String: String] = [:], payload: Payload) throws -> HTTPHeaders {
guard let url = URL(string: urlString) else {
throw S3AdapterError(identifier: "invalid-url", reason: "Invalid URL", source: .capture())
}

let dates = self.getDates(Date())
let bodyDigest = try SHA256.hash(payload ?? "".convertToData()).hexEncodedString()
let bodyDigest = try payload.hashed()
var updatedHeaders = self.updateHeaders(headers, url: url, longDate: dates.long, bodyDigest: bodyDigest)

if httpMethod == .PUT {
updatedHeaders["Content-MD5"] = try MD5.hash(payload ?? "".convertToData()).hexEncodedString()
if httpMethod == .PUT && payload.isBytes {
// TODO: Figure out why S3 would fail with this
updatedHeaders["Content-MD5"] = try MD5.hash(payload.bytes).hexEncodedString()
}

updatedHeaders["Authorization"] = try self.generateAuthHeader(httpMethod, url: url, headers: updatedHeaders, bodyDigest: bodyDigest, dates: dates)

if httpMethod == .PUT {
updatedHeaders["Content-Length"] = payload?.count.description ?? "".convertToData().count.description
updatedHeaders["Content-Length"] = payload.size
if url.pathExtension != "" {
updatedHeaders["Content-Type"] = url.pathExtension
}
}


if payload.isUnsigned {
updatedHeaders["x-amz-content-sha256"] = bodyDigest
}

var headers = HTTPHeaders()
for (key, value) in updatedHeaders {
headers.add(name: key, value: value)
Expand Down
File renamed without changes.
17 changes: 10 additions & 7 deletions Sources/S3Storage/S3Adapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extension Date {
}

extension AdapterIdentifier {
/// The main Local adapter identifier.
/// The main AWS S3 adapter identifier.
public static var s3: AdapterIdentifier<S3Adapter> {
return .init("s3")
}
Expand All @@ -59,7 +59,7 @@ public class S3Adapter: Adapter {
let service = "s3"

/// Create a new Local adapter.
public init(accessKey: String, secretKey: String, region: Region, securityToken: String? = nil) {
public init(accessKey: String, secretKey: String, region: Region, securityToken: String? = nil) throws {
self.accessKey = accessKey
self.secretKey = secretKey
self.region = region
Expand All @@ -78,7 +78,7 @@ extension S3Adapter {
guard let url = URL(string: self.region.host + bucket.finished(with: "/") + object) else {
throw S3AdapterError(identifier: "write", reason: "Couldnt not generate a valid URL path.", source: .capture())
}
let headers = try self.generateAuthHeader(.PUT, urlString: url.absoluteString, payload: content)
let headers = try self.generateAuthHeader(.PUT, urlString: url.absoluteString, payload: .bytes(content))

let request = Request(using: container)
request.http.method = .PUT
Expand All @@ -95,7 +95,7 @@ extension S3Adapter {
guard let url = URL(string: self.region.host + bucket.finished(with: "/") + object) else {
throw S3AdapterError(identifier: "get", reason: "Couldnt not generate a valid URL path.", source: .capture())
}
let headers = try self.generateAuthHeader(.DELETE, urlString: url.absoluteString, payload: nil)
let headers = try self.generateAuthHeader(.DELETE, urlString: url.absoluteString, payload: .none)
let request = Request(using: container)
request.http.method = .DELETE
request.http.headers = headers
Expand All @@ -113,7 +113,7 @@ extension S3Adapter {
guard let url = URL(string: self.region.host + bucket.finished(with: "/") + object) else {
throw S3AdapterError(identifier: "get", reason: "Couldnt not generate a valid URL path.", source: .capture())
}
let headers = try self.generateAuthHeader(.GET, urlString: url.absoluteString, payload: nil)
let headers = try self.generateAuthHeader(.GET, urlString: url.absoluteString, payload: .none)
let request = Request(using: container)
request.http.method = .GET
request.http.headers = headers
Expand All @@ -128,7 +128,7 @@ extension S3Adapter {

public func listObjects(in bucket: String, prefix: String?, on container: Container) throws -> EventLoopFuture<[ObjectInfo]> {
let client = try container.make(Client.self)
var urlComponents = URLComponents(string: self.region.host + bucket.finished(with: "/"))
var urlComponents = URLComponents(string: self.region.host + bucket.finished(with: "/"))
urlComponents?.queryItems?.append(URLQueryItem(name: "list-type", value: "2"))
if let prefix = prefix {
urlComponents?.queryItems?.append(URLQueryItem(name: "prefix", value: prefix))
Expand All @@ -138,12 +138,15 @@ extension S3Adapter {
throw S3AdapterError(identifier: "list", reason: "Couldnt not generate a valid URL path.", source: .capture())
}

let headers = try self.generateAuthHeader(.GET, urlString: url.absoluteString, headers: ["Content-Type": "application/json"], payload: nil)
let headers = try self.generateAuthHeader(.GET, urlString: url.absoluteString, payload: .none)
let request = Request(using: container)
request.http.method = .GET
request.http.headers = headers
request.http.url = url
return try client.respond(to: request).map(to: [ObjectInfo].self) { response in
guard response.http.status == .ok else {
throw S3AdapterError(identifier: "list", reason: "Error: \(response.http.status.reasonPhrase). There requested returned a \(response.http.status.code)", source: .capture())
}
guard let data = response.http.body.data else {
throw S3AdapterError(identifier: "list", reason: "Couldnt not extract the data from the request.", source: .capture())
}
Expand Down

0 comments on commit df99d74

Please sign in to comment.