-
-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #102 from swift-aws/glacier_fixes
fixes for Glacier Service
- Loading branch information
Showing
5 changed files
with
205 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
Sources/AWSSDKSwift/Middlewares/Glacier/GlacierRequestMiddleware.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import Foundation | ||
import AWSSDKSwiftCore | ||
|
||
let MEGA_BYTE = 1024 * 1024 | ||
|
||
public struct GlacierRequestMiddleware: AWSRequestMiddleware { | ||
|
||
let apiVersion: String | ||
|
||
public init (apiVersion: String) { | ||
self.apiVersion = apiVersion | ||
} | ||
|
||
public func chain(request: AWSRequest) throws -> AWSRequest { | ||
var request = request | ||
request.addValue(apiVersion, forHTTPHeaderField: "x-amz-glacier-version") | ||
|
||
let treeHashHeader = "x-amz-sha256-tree-hash" | ||
|
||
if request.httpHeaders[treeHashHeader] == nil { | ||
if let data = try request.body.asData() { | ||
let treeHash = computeTreeHash(data).hexdigest() | ||
request.addValue(treeHash, forHTTPHeaderField: treeHashHeader) | ||
} | ||
} | ||
|
||
return request | ||
} | ||
|
||
// ComputeTreeHash builds a tree hash root node given a Data Object | ||
// Glacier tree hash to be derived from SHA256 hashes of 1MB | ||
// chucks of the data. | ||
// | ||
// See http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html for more information. | ||
// | ||
fileprivate func computeTreeHash(_ data: Data) -> [UInt8] { | ||
var shas: [[UInt8]] = [] | ||
|
||
if data.count < MEGA_BYTE { | ||
shas.append(sha256(data)) | ||
} else { | ||
var numParts = data.count / MEGA_BYTE | ||
if data.count % MEGA_BYTE > 0 { | ||
numParts += 1 | ||
} | ||
|
||
var start: Int | ||
var end: Int | ||
|
||
for partNum in 0..<numParts { | ||
start = partNum * MEGA_BYTE | ||
if partNum == numParts - 1 { | ||
end = data.count - 1 | ||
} else { | ||
end = start + MEGA_BYTE - 1 | ||
} | ||
shas.append(sha256(data.subdata(in: Range(start...end)))) | ||
} | ||
} | ||
|
||
while shas.count > 1 { | ||
var tmpShas: [[UInt8]] = [] | ||
shas.forEachSlice(2, { | ||
let pair = $0 | ||
guard var bytes1 = pair.first else { return } | ||
|
||
if pair.count > 1, var bytes2 = pair.last { | ||
tmpShas.append(sha256(&bytes1, &bytes2)) | ||
} else { | ||
tmpShas.append(bytes1) | ||
} | ||
}) | ||
shas = tmpShas | ||
} | ||
|
||
return shas[0] | ||
} | ||
|
||
} | ||
|
||
extension Array { | ||
/* | ||
[1,2,3,4,5].forEachSlice(2, { print($0) }) | ||
=> [1, 2] | ||
=> [3, 4] | ||
=> [5] | ||
*/ | ||
public func forEachSlice(_ n: Int, _ body: (ArraySlice<Element>) throws -> Void) rethrows { | ||
assert(n > 0, "n require to be greater than 0") | ||
|
||
for from in stride(from: self.startIndex, to: self.endIndex, by: n) { | ||
let to = Swift.min(from + n, self.endIndex) | ||
try body(self[from..<to]) | ||
} | ||
} | ||
} |
Oops, something went wrong.