vapor / http

🚀 Non-blocking, event-driven HTTP built on Swift NIO.
MIT License
240 stars 65 forks source link

Compression middleware #342

Closed satishbabariya closed 4 years ago

satishbabariya commented 5 years ago

By introducing new Compression Middleware Package,

  1. We can drop zlib system dependency and introduce vendored copy of zlib, it will make building vapor and nio more batter on other platforms.
  2. Able to Give Configure Options for Compression Algorithm like gzip and deflate. (solve NIO issue 26)
  3. Introducing Compression as a Middleware will remove dependency like NIOHTTPCompression and zlib system

Example API

class CompressionMiddleware: Middleware {

    struct Configuration {

        enum CompressionAlgorithm {
            case gzip(scheme .... )
            case deflate
        }

        let compressionAlgorithm: CompressionAlgorithm
        let compressionLeval: Int

        .......
    }

    public func respond(to request: Request, chainingTo next: Responder) throws -> EventLoopFuture<Response> {

        guard let acceptEncoding = request.http.headers[.acceptEncoding].first, acceptEncoding == "gzip" else {
            return try next.respond(to: request)
        }

        let response = try next.respond(to: request)

        return response.map { response in
            response.http.headers.replaceOrAdd(name: .contentEncoding, value: "gzip")

            // Do Compression directly.

Currently vapor has only one config for compression "supportCompression: Bool" and HTTPResponseCompressor is i think quite lacking.

also this issue can be move to Vapor for further discussion.

weissi commented 5 years ago

we could/should also work together here and come up with a better API for HTTPResponseCompressor. I know @kjessup from Perfect also wants a better API here.

satishbabariya commented 5 years ago

@weissi we can enhance HTTPResponseCompressor API but that would not help here https://github.com/vapor/http/blob/master/Sources/HTTPKit/Server/HTTPServer.swift#L218,

Currently, the HTTPResponseCompressor is at the core of vapor/http and what we want is to make Compression as Pugglable and Unplaggable. like,

middleware.use(GZipMiddleware(configuration: ...))

and if we use enhanced HTTPResponseCompressor API in that case we need to pass config to the HTTPServerConfig and that would be really messy (-1 form me)

weissi commented 5 years ago

@satishbabariya note that NIO's pipelines are mutable, so you can add and remove HTTPResponseCompressor at runtime trough channel.pipeline.add(Handler) and channel.pipeline.remove(Handler)

satishbabariya commented 5 years ago

Yeah, that also an option but wouldn't it will require to pass compressor configurations through NIOServerConfig instead of the support compression flag, wouldn't it make more complications for the end user?, what's your take on this @tanner0101

tanner0101 commented 5 years ago

I'd prefer to improve NIO's NIOHTTPCompression module and not duplicate work here. Maybe as a middle ground NIO could expose methods outside of just the ChannelHandler for doing compression so that we could easily wrap that in a Vapor Middleware. I'd also be interested to see how other frameworks handle this because it's not immediately clear to me why you'd want to configure compression on a per-route basis.