|
88 | 88 | import java.util.List; |
89 | 89 | import java.util.Map; |
90 | 90 | import java.util.Set; |
| 91 | +import java.util.concurrent.ConcurrentHashMap; |
91 | 92 | import java.util.concurrent.CompletableFuture; |
92 | 93 | import java.util.concurrent.TimeUnit; |
93 | 94 | import java.util.concurrent.atomic.AtomicBoolean; |
@@ -2252,6 +2253,88 @@ public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int |
2252 | 2253 | await(); |
2253 | 2254 | } |
2254 | 2255 |
|
| 2256 | + @Test |
| 2257 | + public void testResponseCompressionEnabledMixedStreams() throws Exception { |
| 2258 | + waitFor(6); |
| 2259 | + String expected = TestUtils.randomAlphaString(1000); |
| 2260 | + server.close(); |
| 2261 | + server = vertx.createHttpServer(new HttpServerOptions(serverOptions).setCompressionSupported(true)); |
| 2262 | + server.requestHandler(req -> { |
| 2263 | + req.response().end(expected); |
| 2264 | + }); |
| 2265 | + startServer(); |
| 2266 | + TestClient client = new TestClient(); |
| 2267 | + client.connect(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, request -> { |
| 2268 | + // Stream 1: with compression |
| 2269 | + int id1 = request.nextStreamId(); |
| 2270 | + // Stream 2: without compression |
| 2271 | + int id2 = request.nextStreamId(); |
| 2272 | + // Stream 3: with compression |
| 2273 | + int id3 = request.nextStreamId(); |
| 2274 | + Map<Integer, ByteArrayOutputStream> streamData = new ConcurrentHashMap<>(); |
| 2275 | + streamData.put(id1, new ByteArrayOutputStream()); |
| 2276 | + streamData.put(id2, new ByteArrayOutputStream()); |
| 2277 | + streamData.put(id3, new ByteArrayOutputStream()); |
| 2278 | + request.decoder.frameListener(new Http2EventAdapter() { |
| 2279 | + @Override |
| 2280 | + public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception { |
| 2281 | + vertx.runOnContext(v -> { |
| 2282 | + if (streamId == id1 || streamId == id3) { |
| 2283 | + // Stream with accept-encoding: gzip should be compressed |
| 2284 | + assertEquals("gzip", headers.get(HttpHeaderNames.CONTENT_ENCODING).toString()); |
| 2285 | + } else { |
| 2286 | + // Stream without accept-encoding should not be compressed |
| 2287 | + assertFalse(headers.contains(HttpHeaderNames.CONTENT_ENCODING)); |
| 2288 | + } |
| 2289 | + complete(); |
| 2290 | + }); |
| 2291 | + } |
| 2292 | + @Override |
| 2293 | + public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream) throws Http2Exception { |
| 2294 | + byte[] bytes = new byte[data.readableBytes()]; |
| 2295 | + data.readBytes(bytes); |
| 2296 | + ByteArrayOutputStream buf = streamData.get(streamId); |
| 2297 | + buf.write(bytes, 0, bytes.length); |
| 2298 | + if (endOfStream) { |
| 2299 | + byte[] allBytes = buf.toByteArray(); |
| 2300 | + vertx.runOnContext(v -> { |
| 2301 | + if (streamId == id1 || streamId == id3) { |
| 2302 | + // Compressed stream - decode gzip |
| 2303 | + String decoded; |
| 2304 | + try { |
| 2305 | + GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(allBytes)); |
| 2306 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| 2307 | + while (true) { |
| 2308 | + int i = in.read(); |
| 2309 | + if (i == -1) { |
| 2310 | + break; |
| 2311 | + } |
| 2312 | + baos.write(i); |
| 2313 | + } |
| 2314 | + decoded = baos.toString(); |
| 2315 | + } catch (IOException e) { |
| 2316 | + fail(e); |
| 2317 | + return; |
| 2318 | + } |
| 2319 | + assertEquals(expected, decoded); |
| 2320 | + } else { |
| 2321 | + // Uncompressed stream - plain text |
| 2322 | + assertEquals(expected, new String(allBytes, StandardCharsets.UTF_8)); |
| 2323 | + } |
| 2324 | + complete(); |
| 2325 | + }); |
| 2326 | + } |
| 2327 | + return super.onDataRead(ctx, streamId, data, padding, endOfStream); |
| 2328 | + } |
| 2329 | + }); |
| 2330 | + request.encoder.writeHeaders(request.context, id1, GET("/").add("accept-encoding", "gzip"), 0, true, request.context.newPromise()); |
| 2331 | + request.encoder.writeHeaders(request.context, id2, GET("/"), 0, true, request.context.newPromise()); |
| 2332 | + request.encoder.writeHeaders(request.context, id3, GET("/").add("accept-encoding", "gzip"), 0, true, request.context.newPromise()); |
| 2333 | + request.context.flush(); |
| 2334 | + }); |
| 2335 | + await(); |
| 2336 | + } |
| 2337 | + |
2255 | 2338 | @Test |
2256 | 2339 | public void testRequestCompressionEnabled() throws Exception { |
2257 | 2340 | String expected = TestUtils.randomAlphaString(1000); |
|
0 commit comments