Skip to content

Commit 47dd02d

Browse files
committed
Correctly add the idle state handler to a NetSocket when using SSL.
Motivation: TLS NetSocket sets the idle state handler after the chunked write handler which more aggressively closes connections when sending a large file. Changes: When configuring a NetSocket, add the idle state handler after the chunked write handler. Add HTTP TLS send file tests.
1 parent 467e6aa commit 47dd02d

4 files changed

Lines changed: 43 additions & 15 deletions

File tree

vertx-core/src/main/java/io/vertx/core/net/impl/NetServerImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,16 @@ protected void initChannel(ChannelPipeline pipeline, boolean ssl) {
266266
if (options.getLogActivity()) {
267267
pipeline.addLast("logging", new LoggingHandler(options.getActivityLogDataFormat()));
268268
}
269-
if (ssl || !options.isFileRegionEnabled() || !vertx.transport().supportFileRegion() || (options.getTrafficShapingOptions() != null && options.getTrafficShapingOptions().getOutboundGlobalBandwidth() > 0)) {
270-
// only add ChunkedWriteHandler when SSL is enabled or FileRegion isn't supported or when outbound traffic shaping is enabled
271-
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); // For large file / sendfile support
272-
}
273269
int idleTimeout = options.getIdleTimeout();
274270
int readIdleTimeout = options.getReadIdleTimeout();
275271
int writeIdleTimeout = options.getWriteIdleTimeout();
276272
if (idleTimeout > 0 || readIdleTimeout > 0 || writeIdleTimeout > 0) {
277273
pipeline.addLast("idle", new IdleStateHandler(readIdleTimeout, writeIdleTimeout, idleTimeout, options.getIdleTimeoutUnit()));
278274
}
275+
if (ssl || !options.isFileRegionEnabled() || !vertx.transport().supportFileRegion() || (options.getTrafficShapingOptions() != null && options.getTrafficShapingOptions().getOutboundGlobalBandwidth() > 0)) {
276+
// only add ChunkedWriteHandler when SSL is enabled or FileRegion isn't supported or when outbound traffic shaping is enabled
277+
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); // For large file / sendfile support
278+
}
279279
}
280280

281281
protected GlobalTrafficShapingHandler createTrafficShapingHandler() {

vertx-core/src/test/java/io/vertx/tests/http/sendfile/Http1xSendFileTest.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import io.vertx.core.http.HttpServerOptions;
1717
import io.vertx.core.http.PoolOptions;
1818
import io.vertx.core.impl.Utils;
19+
import io.vertx.core.net.NetClientOptions;
1920
import io.vertx.test.core.TestUtils;
2021
import org.junit.Assume;
2122
import org.junit.Test;
@@ -48,7 +49,11 @@ public void testSendFileFailsWhenClientClosesConnection() throws Exception {
4849
}
4950
});
5051
startServer(testAddress);
51-
vertx.createNetClient().connect(testAddress).onComplete(onSuccess(socket -> {
52+
vertx.createNetClient(new NetClientOptions()
53+
.setSsl(createBaseClientOptions().isSsl())
54+
.setHostnameVerificationAlgorithm("")
55+
.setTrustAll(true)
56+
).connect(testAddress).onComplete(onSuccess(socket -> {
5257
socket.write("GET / HTTP/1.1\r\n\r\n");
5358
socket.close();
5459
}));
@@ -101,14 +106,8 @@ private int retrieveFileFromServer(File file, HttpServerOptions options) throws
101106
});
102107
startServer(testAddress);
103108
long now = System.currentTimeMillis();
104-
Integer len = getFile().await();
105-
assertEquals((int)len, file.length());
106-
return (int) (System.currentTimeMillis() - now);
107-
}
108-
109-
private Future<Integer> getFile() {
110109
int[] length = {0};
111-
return client.request(requestOptions)
110+
Integer len = client.request(requestOptions)
112111
.compose(req -> req.send()
113112
.compose(resp -> {
114113
resp.handler(buff -> {
@@ -121,7 +120,8 @@ private Future<Integer> getFile() {
121120
resp.exceptionHandler(this::fail);
122121
return resp.end();
123122
}))
124-
.map(v -> length[0]);
123+
.map(v -> length[0]).await();
124+
assertEquals((int)len, file.length());
125+
return (int) (System.currentTimeMillis() - now);
125126
}
126-
127127
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2011-2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.tests.http.sendfile;
12+
13+
import io.vertx.core.http.HttpClientOptions;
14+
import io.vertx.core.http.HttpServerOptions;
15+
import io.vertx.test.tls.Cert;
16+
17+
public class Http1xTLSSendFileTest extends Http1xSendFileTest {
18+
19+
@Override
20+
protected HttpServerOptions createBaseServerOptions() {
21+
return super.createBaseServerOptions().setSsl(true).setKeyCertOptions(Cert.SERVER_JKS.get());
22+
}
23+
24+
@Override
25+
protected HttpClientOptions createBaseClientOptions() {
26+
return super.createBaseClientOptions().setSsl(true).setTrustAll(true);
27+
}
28+
}

vertx-core/src/test/java/io/vertx/tests/http/sendfile/HttpSendFileTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ public void testSendFileWithRandomAccessFileRange() throws Exception {
354354

355355
private RandomAccessFile testSendFileWithFileChannel(int flen, BiFunction<RandomAccessFile, HttpServerResponse, Future<?>> sender,
356356
String expectedContentType, long expectedLength) throws Exception {
357-
Assume.assumeTrue(this instanceof Http1xSendFileTest);
357+
Assume.assumeTrue(this.getClass() == Http1xSendFileTest.class);
358358
File file = TestUtils.tmpFile(".dat", flen);
359359
RandomAccessFile raf = new RandomAccessFile(file, "r");
360360
server.requestHandler(req -> sender.apply(raf, req.response()).onComplete(onSuccess(v -> testComplete())));

0 commit comments

Comments
 (0)