Skip to content

Commit 5224240

Browse files
committed
The Vert.x HTTP server does not handle anymore WebSocket upgrades when the client presents a request with a connection header containing a close header (like nginx can send) and instead close the connection.
The server now will not close the connection when it is not persistent in case of a WebSocket upgrade.
1 parent 39293ff commit 5224240

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
lines changed

src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,17 @@ public long concurrency() {
183183
}
184184

185185
/**
186-
* @return a raw {@code NetSocket} - for internal use
186+
* @return a raw {@code NetSocket} - for internal use - must be called from event-loop
187187
*/
188188
public NetSocketInternal toNetSocket() {
189-
removeChannelHandlers();
190-
NetSocketImpl socket = new NetSocketImpl(context, chctx, null, metrics(), false);
191-
socket.metric(metric());
192189
evictionHandler.handle(null);
193-
chctx.pipeline().replace("handler", "handler", VertxHandler.create(ctx -> socket));
194-
return socket;
190+
chctx.pipeline().replace("handler", "handler", VertxHandler.create(ctx -> {
191+
NetSocketImpl socket = new NetSocketImpl(context, ctx, null, metrics(), false);
192+
socket.metric(metric());
193+
return socket;
194+
}));
195+
VertxHandler<NetSocketImpl> handler = (VertxHandler<NetSocketImpl>) chctx.pipeline().get(VertxHandler.class);
196+
return handler.getConnection();
195197
}
196198

197199
private HttpRequest createRequest(

src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public HttpServerMetrics metrics() {
150150

151151
public void handleMessage(Object msg) {
152152
assert msg != null;
153-
if (requestInProgress == null && !keepAlive) {
153+
if (requestInProgress == null && !keepAlive && webSocket == null) {
154154
// Discard message
155155
return;
156156
}
@@ -247,7 +247,7 @@ void responseComplete() {
247247
handleNext(next);
248248
}
249249
} else {
250-
if (requestInProgress == request) {
250+
if (requestInProgress == request || webSocket != null) {
251251
// Deferred
252252
} else {
253253
flushAndClose();

src/test/java/io/vertx/core/http/WebSocketTest.java

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
package io.vertx.core.http;
1313

1414

15+
import io.netty.channel.ChannelPipeline;
1516
import io.netty.handler.codec.http.HttpHeaderNames;
16-
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
17-
import io.netty.handler.codec.http.websocketx.WebSocket13FrameDecoder;
18-
import io.netty.handler.codec.http.websocketx.WebSocket13FrameEncoder;
19-
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
17+
import io.netty.handler.codec.http.websocketx.*;
2018
import io.netty.util.ReferenceCountUtil;
2119
import io.vertx.core.AbstractVerticle;
2220
import io.vertx.core.AsyncResult;
@@ -2952,6 +2950,44 @@ private void testCloseCustomPayloadFromClient(Consumer<WebSocket> closeOp) {
29522950
await();
29532951
}
29542952

2953+
@Test
2954+
public void testServerWebSocketHandshakeWithNonPersistentConnection() {
2955+
server = vertx.createHttpServer();
2956+
server.webSocketHandler(ws -> {
2957+
ws.frameHandler(frame -> {
2958+
ws.close();
2959+
});
2960+
});
2961+
server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v1 -> {
2962+
handshake(vertx.createHttpClient(), req -> {
2963+
MultiMap headers = req.headers();
2964+
headers.add("Connection", "close");
2965+
req.send(onSuccess(resp -> {
2966+
assertEquals(101, resp.statusCode());
2967+
resp.endHandler(v -> {
2968+
Http1xClientConnection conn = (Http1xClientConnection) req.connection();
2969+
NetSocketInternal soi = conn.toNetSocket();
2970+
soi.messageHandler(msg -> {
2971+
if (msg instanceof CloseWebSocketFrame) {
2972+
soi.close();
2973+
}
2974+
});
2975+
ChannelPipeline pipeline = soi.channelHandlerContext().pipeline();
2976+
pipeline.addBefore("handler", "encoder", new WebSocket13FrameEncoder(true));
2977+
pipeline.addBefore("handler", "decoder", new WebSocket13FrameDecoder(false, false, 1000));
2978+
pipeline.remove("codec");
2979+
soi.writeMessage(new PingWebSocketFrame()).onComplete(onSuccess(written -> {
2980+
}));
2981+
soi.closeHandler(v2 -> {
2982+
testComplete();
2983+
});
2984+
});
2985+
}));
2986+
});
2987+
}));
2988+
await();
2989+
}
2990+
29552991
@Test
29562992
public void testServerCloseHandshake() {
29572993
short status = (short)(4000 + TestUtils.randomPositiveInt() % 100);
@@ -2970,8 +3006,10 @@ public void testServerCloseHandshake() {
29703006
assertEquals(101, resp.statusCode());
29713007
Http1xClientConnection conn = (Http1xClientConnection) req.connection();
29723008
NetSocketInternal soi = conn.toNetSocket();
2973-
soi.channelHandlerContext().pipeline().addBefore("handler", "encoder", new WebSocket13FrameEncoder(true));
2974-
soi.channelHandlerContext().pipeline().addBefore("handler", "decoder", new WebSocket13FrameDecoder(false, false, 1000));
3009+
ChannelPipeline pipeline = soi.channelHandlerContext().pipeline();
3010+
pipeline.addBefore("handler", "encoder", new WebSocket13FrameEncoder(true));
3011+
pipeline.addBefore("handler", "decoder", new WebSocket13FrameDecoder(false, false, 1000));
3012+
pipeline.remove("codec");
29753013
String reason = randomAlphaString(10);
29763014
soi.writeMessage(new CloseWebSocketFrame(status, reason));
29773015
AtomicBoolean closeFrameReceived = new AtomicBoolean();

0 commit comments

Comments
 (0)