Add shouldGzipResponse

This commit is contained in:
Matthias Neeracher 2020-02-16 22:20:02 +01:00
parent 1550ec1298
commit eaca6dde6a

View File

@ -3,7 +3,7 @@ import Vapor
import Foundation import Foundation
import ZIPFoundation import ZIPFoundation
/// Server Gzip middlere: /// Server Gzip middleware:
/// 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",
public struct GzipServerMiddleware: Middleware, ServiceType { public struct GzipServerMiddleware: Middleware, ServiceType {
@ -11,22 +11,37 @@ public struct GzipServerMiddleware: Middleware, ServiceType {
return .init() return .init()
} }
private let shouldGzip: (_ request: Request) -> Bool private let shouldGzipRequest: (_ request: Request) -> Bool
private let shouldGzipResponse: (_ response: Response) -> Bool
/// The `shouldGzip` closure is asked for every request whether that request /// The `shouldGzip` closure is asked for every request whether that request
/// should allow response gzipping. Returns `true` always by default. /// should allow response gzipping. Returns `true` always by default.
public init(shouldGzip: @escaping (_ request: Request) -> Bool = { _ in true }) { public init(shouldGzip: @escaping (_ request: Request) -> Bool = { _ in true }) {
self.shouldGzip = shouldGzip self.shouldGzipRequest = shouldGzip
self.shouldGzipResponse = { _ in true }
}
/// The `shouldGzipRequest` closure is asked for every request whether that request
/// should allow response gzipping. `shouldGzipResponse` asks the same for the response.
/// Both return`true` always by default.
public init(shouldGzipRequest: @escaping (_ request: Request) -> Bool = { _ in true },
shouldGzipResponse: @escaping (_ response: Response) -> Bool = { _ in true }
) {
self.shouldGzipRequest = shouldGzipRequest
self.shouldGzipResponse = shouldGzipResponse
} }
public func respond(to request: Request, chainingTo next: Responder) throws -> EventLoopFuture<Response> { public func respond(to request: Request, chainingTo next: Responder) throws -> EventLoopFuture<Response> {
let acceptsGzip = request.http.headers[.acceptEncoding].first?.contains("gzip") ?? false let acceptsGzip = request.http.headers[.acceptEncoding].first?.contains("gzip") ?? false
guard acceptsGzip && shouldGzip(request) else { let response = try next.respond(to: request)
return try next.respond(to: request) guard acceptsGzip && shouldGzipRequest(request) else {
return response
} }
let response = try next.respond(to: request)
return response.flatMap { response in return response.flatMap { response in
guard self.shouldGzipResponse(response) else {
return request.future(response)
}
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