Skip to content

Http2 server - compressed and uncompressed responses over same connection #5896

@taliano89

Description

@taliano89

Version

5.0.6

Context

Hi, I've encountered the problem with server compression and http2 connection reuse. The problem is in VertxCompressorHttp2ConnectionEncoder

As soon as you send one response that is uncompressed(for instance content-encoding:identity for some small healthcheck endpoint) the next method will switch the encoder from compressed to plain. It will do so only once, so then when you send compressed body, you'll get content-encoding: gzip/zstd but body will be uncompressed cause the codec was already switched to plain by this line delegate = plainEncoder;

   String contentEncodingToApply = determineContentEncodingToApply(ctx, streamId, responseHeaders);
   if (contentEncodingToApply == null || contentEncodingToApply.equalsIgnoreCase(IDENTITY.toString())) {
     if (responseHeaders.contains(CONTENT_ENCODING, IDENTITY)) {
       responseHeaders.remove(CONTENT_ENCODING);
     }
     delegate = plainEncoder;
   } else {
     responseHeaders.set(CONTENT_ENCODING, contentEncodingToApply);
   }
 }

This leads to a client exception like

io.netty.handler.codec.compression.DecompressionException: Input is not in the GZIP format
	at io.netty.handler.codec.compression.JdkZlibDecoder.readGZIPHeader(JdkZlibDecoder.java:341)

So the response body does not match content-encoding header. Also user should not be forced to use all compressed or all uncompressed requests/response per connection. Described scenario worked properly with vertx 4.*

Steps to reproduce

  1. Create http server with http2 and server compression.
  2. Implement first endpoint - it should return anything and put response header content-encoding : identity.
  3. Implement second endpoint- return anything without additional header to allow compression
  4. Create http client with http2 support. Make to sequential requests to endpoint without compression and endpoint with compression.
  5. On the second response you'll receive content-encoding: * but response body is not actually compressed which leads to decompression exception on the client

Do you have a reproducer?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions