Skip to content

Commit 06dea51

Browse files
author
Christoph Läubrich
committed
Prepare for new testcase
1 parent ce5396b commit 06dea51

File tree

2 files changed

+61
-138
lines changed

2 files changed

+61
-138
lines changed

src/main/java/io/github/laeubi/httpclient/NettyWebSocketServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) thro
9393

9494
// WebSocket protocol handler
9595
WebSocketServerProtocolConfig wsConfig = WebSocketServerProtocolConfig.newBuilder()
96-
.websocketPath("/websocket")
96+
.websocketPath("/http")
9797
.checkStartsWith(true)
9898
.build();
9999
ch.pipeline().addLast(new WebSocketServerProtocolHandler(wsConfig));

src/test/java/io/github/laeubi/httpclient/JavaHttpClientWebSocketTest.java

Lines changed: 60 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
/**
2525
* Tests for WebSocket support with Java HttpClient.
2626
*
27-
* This test demonstrates the issue from JDK-8361305 where:
28-
* - Direct WebSocket connection (ws://) works fine
29-
* - But WebSocket upgrade after HTTP connection to the same endpoint does NOT work properly
27+
* This test demonstrates the issue from JDK-8361305 where: - Direct WebSocket
28+
* connection (ws://) works fine - But WebSocket upgrade after HTTP connection
29+
* to the same endpoint does NOT work properly
3030
*/
3131
public class JavaHttpClientWebSocketTest extends JavaHttpClientBase {
3232

3333
private static final Logger logger = LoggerFactory.getLogger(JavaHttpClientWebSocketTest.class);
34-
34+
3535
private static NettyWebSocketServer wsServer;
3636

3737
@BeforeAll
@@ -51,166 +51,89 @@ public static void stopServers() {
5151
@Test
5252
@DisplayName("Direct WebSocket connection works (ws:// URI)")
5353
public void testDirectWebSocketConnection() throws Exception {
54-
logger.info("\n=== Testing Direct WebSocket Connection ===");
55-
56-
HttpClient client = HttpClient.newHttpClient();
54+
// TODO we want to test what happens if the server ONLY support Webservice
55+
// protocol!
56+
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
5757
WebSocket.Builder webSocketBuilder = client.newWebSocketBuilder();
58-
59-
URI wsUri = URI.create("ws://localhost:" + wsServer.getPort() + "/websocket");
60-
logger.info("Connecting to WebSocket URI: {}", wsUri);
61-
58+
}
59+
60+
@Test
61+
@DisplayName("WebSocket upgrade through HTTP")
62+
public void testWebSocketUpgradeAfterHttp2() throws Exception {
63+
logger.info("\n=== Testing WebSocket Upgrade from HTTP Connection ===");
64+
65+
HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2)
66+
.connectTimeout(Duration.ofSeconds(10)).build();
67+
68+
WebSocket.Builder webSocketBuilder = client.newWebSocketBuilder();
69+
URI wsUri = URI.create("ws://localhost:" + wsServer.getPort() + "/http");
70+
logger.info("Step 2: Attempting WebSocket connection to same endpoint: {}", wsUri);
71+
6272
CountDownLatch messageLatch = new CountDownLatch(1);
6373
AtomicReference<String> receivedMessage = new AtomicReference<>();
64-
74+
AtomicReference<Throwable> errorRef = new AtomicReference<>();
75+
6576
WebSocket.Listener listener = new WebSocket.Listener() {
6677
@Override
6778
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
68-
logger.info("Received message: {}", data);
79+
logger.info("Received WebSocket message: {}", data);
6980
receivedMessage.set(data.toString());
7081
messageLatch.countDown();
7182
return CompletableFuture.completedFuture(null);
7283
}
73-
84+
7485
@Override
7586
public void onOpen(WebSocket webSocket) {
76-
logger.info("WebSocket connection opened");
87+
logger.info("WebSocket connection opened successfully");
7788
WebSocket.Listener.super.onOpen(webSocket);
7889
}
79-
90+
8091
@Override
8192
public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
8293
logger.info("WebSocket closed with status: {}, reason: {}", statusCode, reason);
8394
return CompletableFuture.completedFuture(null);
8495
}
85-
96+
8697
@Override
8798
public void onError(WebSocket webSocket, Throwable error) {
8899
logger.error("WebSocket error", error);
100+
errorRef.set(error);
89101
}
90102
};
91-
92-
CompletableFuture<WebSocket> wsFuture = webSocketBuilder.buildAsync(wsUri, listener);
93-
WebSocket webSocket = wsFuture.get(10, TimeUnit.SECONDS);
94-
assertNotNull(webSocket, "WebSocket should be established");
95-
96-
// Send a message
97-
webSocket.sendText("Hello from client", true).get(5, TimeUnit.SECONDS);
98-
99-
// Wait for response
100-
boolean received = messageLatch.await(10, TimeUnit.SECONDS);
101-
assertTrue(received, "Should receive a response from WebSocket server");
102-
assertEquals("Echo: Hello from client", receivedMessage.get(), "Should receive echoed message");
103-
104-
// Close the connection
105-
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Closing").get(5, TimeUnit.SECONDS);
106-
107-
logger.info("=== Direct WebSocket Connection test completed successfully ===\n");
108-
}
109103

110-
@Test
111-
@DisplayName("WebSocket upgrade after HTTP/2 connection does NOT work (demonstrates JDK-8361305)")
112-
public void testWebSocketUpgradeAfterHttp2() throws Exception {
113-
logger.info("\n=== Testing WebSocket Upgrade after HTTP/2 Connection ===");
114-
115-
// Create a combined server that supports both HTTP/2 upgrade and WebSocket on same port
116-
NettyWebSocketServer combinedServer = new NettyWebSocketServer(9999);
117-
118104
try {
119-
// Create HttpClient configured for HTTP/2
120-
HttpClient client = HttpClient.newBuilder()
121-
.version(HttpClient.Version.HTTP_2)
122-
.connectTimeout(Duration.ofSeconds(10))
123-
.build();
124-
125-
// Step 1: First make a regular HTTP request which may establish HTTP/2 connection
126-
// This simulates a scenario where the client has already connected to the server
127-
java.net.http.HttpRequest httpRequest = java.net.http.HttpRequest.newBuilder()
128-
.uri(URI.create("http://localhost:"+combinedServer.getPort()+"/websocket"))
129-
.GET()
130-
.build();
131-
132-
logger.info("Step 1: Making HTTP request to http://localhost:9090/websocket");
133-
try {
134-
java.net.http.HttpResponse<String> httpResponse = client.send(httpRequest,
135-
java.net.http.HttpResponse.BodyHandlers.ofString());
136-
logger.info("HTTP Response status: {}, version: {}", httpResponse.statusCode(), httpResponse.version());
137-
} catch (Exception e) {
138-
logger.info("HTTP request completed (or failed): {}", e.getMessage());
139-
}
140-
141-
// Step 2: Now try to establish WebSocket connection to the SAME endpoint
142-
// This is where JDK-8361305 issue manifests - trying to upgrade to WebSocket
143-
// after HTTP/2 connection exists
144-
WebSocket.Builder webSocketBuilder = client.newWebSocketBuilder();
145-
URI wsUri = URI.create("ws://localhost:" + combinedServer.getPort() + "/websocket");
146-
logger.info("Step 2: Attempting WebSocket connection to same endpoint: {}", wsUri);
147-
148-
CountDownLatch messageLatch = new CountDownLatch(1);
149-
AtomicReference<String> receivedMessage = new AtomicReference<>();
150-
AtomicReference<Throwable> errorRef = new AtomicReference<>();
151-
152-
WebSocket.Listener listener = new WebSocket.Listener() {
153-
@Override
154-
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
155-
logger.info("Received WebSocket message: {}", data);
156-
receivedMessage.set(data.toString());
157-
messageLatch.countDown();
158-
return CompletableFuture.completedFuture(null);
159-
}
160-
161-
@Override
162-
public void onOpen(WebSocket webSocket) {
163-
logger.info("WebSocket connection opened successfully");
164-
WebSocket.Listener.super.onOpen(webSocket);
165-
}
166-
167-
@Override
168-
public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
169-
logger.info("WebSocket closed with status: {}, reason: {}", statusCode, reason);
170-
return CompletableFuture.completedFuture(null);
171-
}
172-
173-
@Override
174-
public void onError(WebSocket webSocket, Throwable error) {
175-
logger.error("WebSocket error", error);
176-
errorRef.set(error);
177-
}
178-
};
179-
180-
try {
181-
CompletableFuture<WebSocket> wsFuture = webSocketBuilder.buildAsync(wsUri, listener);
182-
WebSocket webSocket = wsFuture.get(10, TimeUnit.SECONDS);
183-
184-
// If we get here, the connection worked
185-
assertNotNull(webSocket, "WebSocket should be established");
186-
logger.info("WebSocket connection established successfully");
187-
188-
// Send a test message
189-
webSocket.sendText("Test message", true).get(5, TimeUnit.SECONDS);
190-
191-
// Wait for response
192-
boolean received = messageLatch.await(10, TimeUnit.SECONDS);
193-
assertTrue(received, "Should receive echo response from WebSocket server");
194-
assertEquals("Echo: Test message", receivedMessage.get(), "Should receive echoed message");
195-
196-
// Assert that WebSocket upgrade was actually performed
197-
combinedServer.assertWebSocketUpgrade();
198-
199-
// Close the connection
200-
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Test complete").get(5, TimeUnit.SECONDS);
201-
202-
logger.info("SUCCESS: WebSocket connection worked after HTTP/2. Issue may be fixed in this Java version.");
203-
} catch (Exception e) {
204-
// This documents the JDK-8361305 issue
205-
logger.error("EXPECTED FAILURE per JDK-8361305: WebSocket upgrade failed after HTTP/2 connection", e);
206-
logger.info("This test documents that WebSocket upgrade does NOT work when HTTP/2 connection exists to the same host.");
207-
// Don't fail the test - this documents the known issue
208-
// In future Java versions where this is fixed, this catch block won't be reached
209-
}
210-
} finally {
211-
combinedServer.stop();
105+
CompletableFuture<WebSocket> wsFuture = webSocketBuilder.buildAsync(wsUri, listener);
106+
WebSocket webSocket = wsFuture.get(10, TimeUnit.SECONDS);
107+
108+
// If we get here, the connection worked
109+
assertNotNull(webSocket, "WebSocket should be established");
110+
logger.info("WebSocket connection established successfully");
111+
112+
// Send a test message
113+
webSocket.sendText("Test message", true).get(5, TimeUnit.SECONDS);
114+
115+
// Wait for response
116+
boolean received = messageLatch.await(10, TimeUnit.SECONDS);
117+
assertTrue(received, "Should receive echo response from WebSocket server");
118+
assertEquals("Echo: Test message", receivedMessage.get(), "Should receive echoed message");
119+
120+
// Assert that WebSocket upgrade was actually performed
121+
wsServer.assertWebSocketUpgrade();
122+
123+
// Close the connection
124+
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Test complete").get(5, TimeUnit.SECONDS);
125+
126+
logger.info("SUCCESS: WebSocket connection worked after HTTP/2. Issue may be fixed in this Java version.");
127+
} catch (Exception e) {
128+
// This documents the JDK-8361305 issue
129+
logger.error("EXPECTED FAILURE per JDK-8361305: WebSocket upgrade failed after HTTP/2 connection", e);
130+
logger.info(
131+
"This test documents that WebSocket upgrade does NOT work when HTTP/2 connection exists to the same host.");
132+
// Don't fail the test - this documents the known issue
133+
// In future Java versions where this is fixed, this catch block won't be
134+
// reached
212135
}
213-
136+
214137
logger.info("=== WebSocket Upgrade test completed ===\n");
215138
}
216139
}

0 commit comments

Comments
 (0)