Skip to content

Commit 2946123

Browse files
committed
Ensured Netty provider uses CONNECT when proxying ws
The WS standard requires that clients use the CONNECT method when proxying WebSockets, even if they aren't using SSL. The Grizzly provider already supported this, but the Netty didn't. I also implemented a test that tested this case.
1 parent 486cc11 commit 2946123

File tree

2 files changed

+45
-25
lines changed

2 files changed

+45
-25
lines changed

src/main/java/com/ning/http/client/providers/netty/NettyAsyncHttpProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ protected final static HttpRequest buildRequest(AsyncHttpClientConfig config, Re
649649
throws IOException {
650650

651651
String method = request.getMethod();
652-
if (allowConnect && proxyServer != null && isSecure(uri)) {
652+
if (allowConnect && proxyServer != null && (isSecure(uri) || isWebSocket(uri.getScheme()))) {
653653
method = HttpMethod.CONNECT.toString();
654654
}
655655
return construct(config, request, new HttpMethod(method), uri, buffer, proxyServer);

src/test/java/com/ning/http/client/websocket/ProxyTunnellingTest.java

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.eclipse.jetty.server.nio.SelectChannelConnector;
2828
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
2929
import org.testng.annotations.AfterClass;
30+
import org.testng.annotations.AfterMethod;
3031
import org.testng.annotations.BeforeClass;
3132
import org.testng.annotations.Test;
3233

@@ -43,39 +44,46 @@ public abstract class ProxyTunnellingTest extends AbstractBasicTest {
4344
int port2;
4445
private Server server2;
4546

46-
@BeforeClass(alwaysRun = true)
4747
public void setUpGlobal() throws Exception {
48-
server2 = new Server();
48+
}
49+
50+
private void setUpServers(Connector server2Connector) throws Exception {
4951

5052
port1 = findFreePort();
5153
port2 = findFreePort();
52-
5354
Connector listener = new SelectChannelConnector();
54-
5555
listener.setHost("127.0.0.1");
5656
listener.setPort(port1);
57-
5857
addConnector(listener);
58+
setHandler(new ConnectHandler());
59+
start();
5960

60-
SslSelectChannelConnector connector = new SslSelectChannelConnector();
61-
connector.setHost("127.0.0.1");
62-
connector.setPort(port2);
61+
server2 = new Server();
62+
63+
server2Connector.setHost("127.0.0.1");
64+
server2Connector.setPort(port2);
65+
66+
server2.addConnector(server2Connector);
67+
68+
server2.setHandler(getWebSocketHandler());
69+
server2.start();
70+
log.info("Local HTTP server started successfully");
71+
72+
}
73+
74+
private void setUpServer() throws Exception {
75+
setUpServers(new SelectChannelConnector());
76+
}
6377

78+
private void setUpSSlServer2() throws Exception {
79+
SslSelectChannelConnector connector = new SslSelectChannelConnector();
6480
ClassLoader cl = getClass().getClassLoader();
6581
URL keystoreUrl = cl.getResource("ssltest-keystore.jks");
6682
String keyStoreFile = new File(keystoreUrl.toURI()).getAbsolutePath();
6783
connector.setKeystore(keyStoreFile);
6884
connector.setKeyPassword("changeit");
6985
connector.setKeystoreType("JKS");
70-
71-
server2.addConnector(connector);
72-
73-
setHandler(new ConnectHandler());
74-
start();
75-
76-
server2.setHandler(getWebSocketHandler());
77-
server2.start();
78-
log.info("Local HTTP server started successfully");
86+
setUpServers(connector);
7987
}
8088

8189
@Override
@@ -88,27 +96,38 @@ public org.eclipse.jetty.websocket.WebSocket doWebSocketConnect(HttpServletReque
8896
};
8997
}
9098

91-
@AfterClass(alwaysRun = true)
99+
@AfterMethod(alwaysRun = true)
92100
public void tearDownGlobal() throws Exception {
93101
stop();
94-
server2.stop();
102+
if (server2 != null) {
103+
server2.stop();
104+
}
105+
server2 = null;
95106
}
96107

97-
protected String getTargetUrl() {
98-
return String.format("wss://127.0.0.1:%d/", port2);
108+
@Test(timeOut = 60000)
109+
public void echoWSText() throws Exception {
110+
setUpServer();
111+
runTest("ws");
99112
}
100113

101114
@Test(timeOut = 60000)
102-
public void echoText() throws Exception {
115+
public void echoWSSText() throws Exception {
116+
setUpSSlServer2();
117+
runTest("wss");
118+
}
103119

104-
ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1);
120+
private void runTest(String protocol) throws Exception {
121+
String targetUrl = String.format("%s://127.0.0.1:%d/", protocol, port2);
122+
123+
ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTP, "127.0.0.1", port1);
105124
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setProxyServer(ps).build();
106125
AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config);
107126
try {
108127
final CountDownLatch latch = new CountDownLatch(1);
109128
final AtomicReference<String> text = new AtomicReference<String>("");
110129

111-
WebSocket websocket = asyncHttpClient.prepareGet(getTargetUrl()).execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(new WebSocketTextListener() {
130+
WebSocket websocket = asyncHttpClient.prepareGet(targetUrl).execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(new WebSocketTextListener() {
112131

113132
@Override
114133
public void onMessage(String message) {
@@ -143,5 +162,6 @@ public void onError(Throwable t) {
143162
} finally {
144163
asyncHttpClient.close();
145164
}
165+
146166
}
147167
}

0 commit comments

Comments
 (0)