From 399ec66bdac8dac7bab629e4dc352f65333df04a Mon Sep 17 00:00:00 2001 From: Matthias Neeracher Date: Sun, 7 Oct 2018 02:09:31 +0200 Subject: [PATCH] Get streaming approach to work after all --- Sources/GzipMiddleware/GzipMiddleware.swift | 40 +++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Sources/GzipMiddleware/GzipMiddleware.swift b/Sources/GzipMiddleware/GzipMiddleware.swift index f0c9f96..fd7cf0c 100644 --- a/Sources/GzipMiddleware/GzipMiddleware.swift +++ b/Sources/GzipMiddleware/GzipMiddleware.swift @@ -3,15 +3,6 @@ import Vapor import Foundation 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: /// 1. checks if the "Accept-Encoding" header contains "gzip" /// 2. if so, compresses the body and sets the response header "Content-Encoding" to "gzip", @@ -39,22 +30,35 @@ public struct GzipServerMiddleware: Middleware, ServiceType { var headers = response.http.headers headers.replaceOrAdd(name: .contentEncoding, value: "gzip") return response.http.body.consumeData(on: request).map { data in - var buffer = Data() + let stream = HTTPChunkedStream(on: request) + let bufSize = 4096 + var buffer = ByteBufferAllocator().buffer(capacity: 16) let header : [UInt8] = [0x1f, 0x8b, 0x08, 0x00] let header2 : [UInt8] = [0x00, 0x03] - buffer.append(contentsOf: header) - buffer.appendLittleEndian(UInt32(Date().timeIntervalSince1970)) - buffer.append(contentsOf: header2) - let crc32 = try Data.compress(size: data.count, bufferSize: 4096, + buffer.write(bytes: header) + buffer.write(integer: UInt32(Date().timeIntervalSince1970), endianness: .little) + buffer.write(bytes: header2) + var write = stream.write(.chunk(buffer)) + let crc32 = try Data.compress(size: data.count, bufferSize: bufSize, provider: {(offset, readSize) -> Data in return data.subdata(in: offset.. Void in - buffer.append(data) + var buffer = ByteBufferAllocator().buffer(capacity: bufSize) + buffer.write(bytes: data) + write = write.flatMap { + return stream.write(.chunk(buffer)) + } }) - buffer.appendLittleEndian(crc32) - buffer.appendLittleEndian(UInt32(data.count)) - let httpResponse = HTTPResponse(status: response.http.status, headers: headers, body: buffer) + write.always { + buffer.clear() + buffer.write(integer: crc32, endianness: .little) + 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) } }