Compress to single data buffer instead of chunked stream
This commit is contained in:
parent
6b2983cbbb
commit
3a6a02deb5
|
@ -11,7 +11,7 @@ let package = Package(
|
||||||
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
|
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
|
||||||
|
|
||||||
// 🤐 Unzip archives
|
// 🤐 Unzip archives
|
||||||
.package(url: "https://github.com/microtherion/ZIPFoundation.git", .upToNextMajor(from: "0.9.7-µ"))
|
.package(url: "https://github.com/microtherion/ZIPFoundation.git", .upToNextMajor(from: "0.9.8-µ"))
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(name: "GzipMiddleware", dependencies: ["Vapor", "ZIPFoundation"]),
|
.target(name: "GzipMiddleware", dependencies: ["Vapor", "ZIPFoundation"]),
|
||||||
|
|
|
@ -3,6 +3,15 @@ import Vapor
|
||||||
import Foundation
|
import Foundation
|
||||||
import ZIPFoundation
|
import ZIPFoundation
|
||||||
|
|
||||||
|
private extension Data {
|
||||||
|
mutating func appendLittleEndian(_ word: UInt32) {
|
||||||
|
self.append(UInt8(word & 0xFF))
|
||||||
|
self.append(UInt8((word >> 8) & 0xFF))
|
||||||
|
self.append(UInt8((word >> 16) & 0xFF))
|
||||||
|
self.append(UInt8((word >> 24) & 0xFF))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Server Gzip middlere:
|
/// Server Gzip middlere:
|
||||||
/// 1. checks if the "Accept-Encoding" header contains "gzip"
|
/// 1. checks if the "Accept-Encoding" header contains "gzip"
|
||||||
/// 2. if so, compresses the body and sets the response header "Content-Encoding" to "gzip",
|
/// 2. if so, compresses the body and sets the response header "Content-Encoding" to "gzip",
|
||||||
|
@ -30,35 +39,22 @@ public struct GzipServerMiddleware: Middleware, ServiceType {
|
||||||
var headers = response.http.headers
|
var headers = response.http.headers
|
||||||
headers.replaceOrAdd(name: .contentEncoding, value: "gzip")
|
headers.replaceOrAdd(name: .contentEncoding, value: "gzip")
|
||||||
return response.http.body.consumeData(on: request).map { data in
|
return response.http.body.consumeData(on: request).map { data in
|
||||||
let stream = HTTPChunkedStream(on: request)
|
var buffer = Data()
|
||||||
let bufSize = 4096
|
|
||||||
var buffer = ByteBufferAllocator().buffer(capacity: bufSize)
|
|
||||||
let header : [UInt8] = [0x1f, 0x8b, 0x08, 0x00]
|
let header : [UInt8] = [0x1f, 0x8b, 0x08, 0x00]
|
||||||
let header2 : [UInt8] = [0x00, 0x03]
|
let header2 : [UInt8] = [0x00, 0x03]
|
||||||
buffer.write(bytes: header)
|
buffer.append(contentsOf: header)
|
||||||
buffer.write(integer: UInt32(Date().timeIntervalSince1970), endianness: .little)
|
buffer.appendLittleEndian(UInt32(Date().timeIntervalSince1970))
|
||||||
buffer.write(bytes: header2)
|
buffer.append(contentsOf: header2)
|
||||||
var write = stream.write(.chunk(buffer))
|
let crc32 = try Data.compress(size: data.count, bufferSize: 4096,
|
||||||
let crc32 = try Data.compress(size: data.count, bufferSize: bufSize,
|
|
||||||
provider: {(offset, readSize) -> Data in
|
provider: {(offset, readSize) -> Data in
|
||||||
return data.subdata(in: offset..<offset+readSize)
|
return data.subdata(in: offset..<offset+readSize)
|
||||||
},
|
},
|
||||||
consumer: { data -> Void in
|
consumer: { data -> Void in
|
||||||
write = write.flatMap {
|
buffer.append(data)
|
||||||
buffer.clear()
|
|
||||||
buffer.write(bytes: data)
|
|
||||||
return stream.write(.chunk(buffer))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
write.always {
|
buffer.appendLittleEndian(crc32)
|
||||||
buffer.clear()
|
buffer.appendLittleEndian(UInt32(data.count))
|
||||||
buffer.write(integer: crc32, endianness: .little)
|
let httpResponse = HTTPResponse(status: response.http.status, headers: headers, body: buffer)
|
||||||
buffer.write(integer: UInt32(data.count), endianness: .little)
|
|
||||||
stream.write(.chunk(buffer)).always {
|
|
||||||
_ = stream.write(.end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let httpResponse = HTTPResponse(status: response.http.status, headers: headers, body: stream)
|
|
||||||
return request.response(http: httpResponse)
|
return request.response(http: httpResponse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user