Skip to content

Commit e2eca0b

Browse files
author
Stephane Landelle
committed
Ensured Netty provider uses CONNECT when proxying ws, port AsyncHttpClient#657 on 1.9
1 parent d7060ca commit e2eca0b

File tree

8 files changed

+79
-56
lines changed

8 files changed

+79
-56
lines changed

src/main/java/com/ning/http/client/AsyncHttpClientConfig.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public class AsyncHttpClientConfig {
6666
protected boolean strict302Handling;
6767

6868
protected ProxyServerSelector proxyServerSelector;
69-
protected boolean useRelativeURIsWithSSLProxies;
69+
protected boolean useRelativeURIsWithConnectProxies;
7070

7171
protected boolean compressionEnabled;
7272
protected String userAgent;
@@ -103,7 +103,7 @@ private AsyncHttpClientConfig(int connectionTimeout,//
103103
boolean strict302Handling, //
104104
ExecutorService applicationThreadPool,//
105105
ProxyServerSelector proxyServerSelector, //
106-
boolean useRelativeURIsWithSSLProxies, //
106+
boolean useRelativeURIsWithConnectProxies, //
107107
boolean compressionEnabled, //
108108
String userAgent,//
109109
Realm realm,//
@@ -134,7 +134,7 @@ private AsyncHttpClientConfig(int connectionTimeout,//
134134
this.removeQueryParamOnRedirect = removeQueryParamOnRedirect;
135135
this.strict302Handling = strict302Handling;
136136
this.proxyServerSelector = proxyServerSelector;
137-
this.useRelativeURIsWithSSLProxies = useRelativeURIsWithSSLProxies;
137+
this.useRelativeURIsWithConnectProxies = useRelativeURIsWithConnectProxies;
138138
this.compressionEnabled = compressionEnabled;
139139
this.userAgent = userAgent;
140140
this.applicationThreadPool = applicationThreadPool == null ? Executors.newCachedThreadPool() : applicationThreadPool;
@@ -417,13 +417,13 @@ public boolean isStrict302Handling() {
417417
}
418418

419419
/**
420-
* @return<code>true</code> if AHC should use relative URIs instead of absolute ones when talking with a SSL proxy,
421-
* otherwise <code>false</code>.
420+
* @return<code>true</code> if AHC should use relative URIs instead of absolute ones when talking with a SSL proxy
421+
* or WebSocket proxy, otherwise <code>false</code>.
422422
*
423-
* @since 1.7.12
423+
* @since 1.8.13
424424
*/
425-
public boolean isUseRelativeURIsWithSSLProxies() {
426-
return useRelativeURIsWithSSLProxies;
425+
public boolean isUseRelativeURIsWithConnectProxies() {
426+
return useRelativeURIsWithConnectProxies;
427427
}
428428

429429
/**
@@ -473,7 +473,7 @@ public static class Builder {
473473
private ProxyServerSelector proxyServerSelector = null;
474474
private boolean useProxySelector = defaultUseProxySelector();
475475
private boolean useProxyProperties = defaultUseProxyProperties();
476-
private boolean useRelativeURIsWithSSLProxies = defaultUseRelativeURIsWithSSLProxies();
476+
private boolean useRelativeURIsWithConnectProxies = defaultUseRelativeURIsWithConnectProxies();
477477
private boolean compressionEnabled = defaultCompressionEnabled();
478478
private String userAgent = defaultUserAgent();
479479
private ExecutorService applicationThreadPool;
@@ -870,15 +870,15 @@ public Builder setStrict302Handling(final boolean strict302Handling) {
870870
}
871871

872872
/**
873-
* Configures this AHC instance to use relative URIs instead of absolute ones when talking with a SSL proxy.
873+
* Configures this AHC instance to use relative URIs instead of absolute ones when talking with a SSL proxy or WebSocket proxy.
874874
*
875-
* @param useRelativeURIsWithSSLProxies
875+
* @param useRelativeURIsWithConnectProxies
876876
* @return this
877877
*
878-
* @since 1.7.2
878+
* @since 1.8.13
879879
*/
880-
public Builder setUseRelativeURIsWithSSLProxies(boolean useRelativeURIsWithSSLProxies) {
881-
this.useRelativeURIsWithSSLProxies = useRelativeURIsWithSSLProxies;
880+
public Builder setUseRelativeURIsWithConnectProxies(boolean useRelativeURIsWithConnectProxies) {
881+
this.useRelativeURIsWithConnectProxies = useRelativeURIsWithConnectProxies;
882882
return this;
883883
}
884884

@@ -995,7 +995,7 @@ else if (hostnameVerifier == null)
995995
strict302Handling, //
996996
applicationThreadPool, //
997997
proxyServerSelector, //
998-
useRelativeURIsWithSSLProxies, //
998+
useRelativeURIsWithConnectProxies, //
999999
compressionEnabled, //
10001000
userAgent,//
10011001
realm,//

src/main/java/com/ning/http/client/AsyncHttpClientConfigBean.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void configureDefaults() {
5858
compressionEnabled = defaultCompressionEnabled();
5959
userAgent = defaultUserAgent();
6060
allowPoolingConnections = defaultAllowPoolingConnections();
61-
useRelativeURIsWithSSLProxies = defaultUseRelativeURIsWithSSLProxies();
61+
useRelativeURIsWithConnectProxies = defaultUseRelativeURIsWithConnectProxies();
6262
maxRequestRetry = defaultMaxRequestRetry();
6363
ioThreadMultiplier = defaultIoThreadMultiplier();
6464
allowPoolingSslConnections = defaultAllowPoolingSslConnections();

src/main/java/com/ning/http/client/AsyncHttpClientConfigDefaults.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ public static boolean defaultAllowPoolingConnections() {
8989
return getBoolean(ASYNC_CLIENT + "allowPoolingConnections", true);
9090
}
9191

92-
public static boolean defaultUseRelativeURIsWithSSLProxies() {
93-
return getBoolean(ASYNC_CLIENT + "useRelativeURIsWithSSLProxies", true);
92+
public static boolean defaultUseRelativeURIsWithConnectProxies() {
93+
return getBoolean(ASYNC_CLIENT + "useRelativeURIsWithConnectProxies", true);
9494
}
9595

9696
public static int defaultMaxRequestRetry() {

src/main/java/com/ning/http/client/providers/grizzly/GrizzlyAsyncHttpProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ private boolean sendAsGrizzlyRequest(final Request request,
871871
httpCtx.establishingTunnel = true;
872872
builder.method(Method.CONNECT);
873873
builder.uri(AsyncHttpProviderUtils.getAuthority(uri));
874-
} else if (secure && config.isUseRelativeURIsWithSSLProxies()){
874+
} else if ((secure || httpCtx.isWSRequest) && config.isUseRelativeURIsWithConnectProxies()){
875875
builder.uri(getNonEmptyPath(uri));
876876
} else {
877877
builder.uri(uri.toUrl());

src/main/java/com/ning/http/client/providers/netty/request/NettyRequestFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private String requestUri(UriComponents uri, ProxyServer proxyServer, HttpMethod
6969
if (method == HttpMethod.CONNECT)
7070
return getAuthority(uri);
7171

72-
else if (proxyServer != null && !(isSecure(uri) && config.isUseRelativeURIsWithSSLProxies()))
72+
else if (proxyServer != null && !(useProxyConnect(uri) && config.isUseRelativeURIsWithConnectProxies()))
7373
return uri.toString();
7474

7575
else {

src/main/java/com/ning/http/client/providers/netty/request/NettyRequestSender.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import static com.ning.http.client.providers.netty.util.HttpUtils.WEBSOCKET;
1616
import static com.ning.http.client.providers.netty.util.HttpUtils.isSecure;
17+
import static com.ning.http.client.providers.netty.util.HttpUtils.useProxyConnect;
1718
import static com.ning.http.util.AsyncHttpProviderUtils.getDefaultPort;
1819
import static com.ning.http.util.AsyncHttpProviderUtils.requestTimeout;
1920
import static com.ning.http.util.ProxyUtils.avoidProxy;
@@ -103,7 +104,7 @@ public <T> ListenableFuture<T> sendRequest(final Request request,//
103104
&& future.getNettyRequest().getHttpRequest().getMethod() == HttpMethod.CONNECT;
104105
boolean useProxy = proxyServer != null && !resultOfAConnect;
105106

106-
if (useProxy && isSecure(uri))
107+
if (useProxy && useProxyConnect(uri))
107108
// SSL proxy, have to handle CONNECT
108109
if (future != null && future.isConnectAllowed())
109110
// CONNECT forced

src/main/java/com/ning/http/client/providers/netty/util/HttpUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ public static boolean isSecure(String scheme) {
5858
public static boolean isSecure(UriComponents uri) {
5959
return isSecure(uri.getScheme());
6060
}
61+
62+
public static boolean useProxyConnect(UriComponents uri) {
63+
return isSecure(uri) || isWebSocket(uri.getScheme());
64+
}
6165
}

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

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,26 @@
1414

1515
import static org.testng.Assert.assertEquals;
1616

17-
import java.io.File;
18-
import java.net.URL;
19-
import java.util.concurrent.CountDownLatch;
20-
import java.util.concurrent.atomic.AtomicReference;
21-
22-
import javax.servlet.http.HttpServletRequest;
23-
2417
import org.eclipse.jetty.server.Connector;
2518
import org.eclipse.jetty.server.Server;
2619
import org.eclipse.jetty.server.handler.ConnectHandler;
2720
import org.eclipse.jetty.server.nio.SelectChannelConnector;
2821
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
29-
import org.testng.annotations.AfterClass;
30-
import org.testng.annotations.BeforeClass;
22+
import org.testng.annotations.AfterMethod;
3123
import org.testng.annotations.Test;
3224

3325
import com.ning.http.client.AsyncHttpClient;
3426
import com.ning.http.client.AsyncHttpClientConfig;
3527
import com.ning.http.client.ProxyServer;
3628
import com.ning.http.client.websocket.TextMessageTest.EchoTextWebSocket;
3729

30+
import javax.servlet.http.HttpServletRequest;
31+
32+
import java.io.File;
33+
import java.net.URL;
34+
import java.util.concurrent.CountDownLatch;
35+
import java.util.concurrent.atomic.AtomicReference;
36+
3837
/**
3938
* Proxy usage tests.
4039
*/
@@ -43,39 +42,46 @@ public abstract class ProxyTunnellingTest extends AbstractBasicTest {
4342
int port2;
4443
private Server server2;
4544

46-
@BeforeClass(alwaysRun = true)
4745
public void setUpGlobal() throws Exception {
48-
server2 = new Server();
46+
}
47+
48+
private void setUpServers(Connector server2Connector) throws Exception {
4949

5050
port1 = findFreePort();
5151
port2 = findFreePort();
52-
5352
Connector listener = new SelectChannelConnector();
54-
5553
listener.setHost("127.0.0.1");
5654
listener.setPort(port1);
57-
5855
addConnector(listener);
56+
setHandler(new ConnectHandler());
57+
start();
5958

60-
SslSelectChannelConnector connector = new SslSelectChannelConnector();
61-
connector.setHost("127.0.0.1");
62-
connector.setPort(port2);
59+
server2 = new Server();
6360

61+
server2Connector.setHost("127.0.0.1");
62+
server2Connector.setPort(port2);
63+
64+
server2.addConnector(server2Connector);
65+
66+
server2.setHandler(getWebSocketHandler());
67+
server2.start();
68+
log.info("Local HTTP server started successfully");
69+
70+
}
71+
72+
private void setUpServer() throws Exception {
73+
setUpServers(new SelectChannelConnector());
74+
}
75+
76+
private void setUpSSlServer2() throws Exception {
77+
SslSelectChannelConnector connector = new SslSelectChannelConnector();
6478
ClassLoader cl = getClass().getClassLoader();
6579
URL keystoreUrl = cl.getResource("ssltest-keystore.jks");
6680
String keyStoreFile = new File(keystoreUrl.toURI()).getAbsolutePath();
6781
connector.setKeystore(keyStoreFile);
6882
connector.setKeyPassword("changeit");
6983
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");
84+
setUpServers(connector);
7985
}
8086

8187
@Override
@@ -88,27 +94,38 @@ public org.eclipse.jetty.websocket.WebSocket doWebSocketConnect(HttpServletReque
8894
};
8995
}
9096

91-
@AfterClass(alwaysRun = true)
97+
@AfterMethod(alwaysRun = true)
9298
public void tearDownGlobal() throws Exception {
9399
stop();
94-
server2.stop();
100+
if (server2 != null) {
101+
server2.stop();
102+
}
103+
server2 = null;
95104
}
96105

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

101112
@Test(timeOut = 60000)
102-
public void echoText() throws Exception {
113+
public void echoWSSText() throws Exception {
114+
setUpSSlServer2();
115+
runTest("wss");
116+
}
117+
118+
private void runTest(String protocol) throws Exception {
119+
String targetUrl = String.format("%s://127.0.0.1:%d/", protocol, port2);
103120

104-
ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1);
121+
ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTP, "127.0.0.1", port1);
105122
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setProxyServer(ps).setAcceptAnyCertificate(true).build();
106-
AsyncHttpClient client = getAsyncHttpClient(config);
123+
AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config);
107124
try {
108125
final CountDownLatch latch = new CountDownLatch(1);
109126
final AtomicReference<String> text = new AtomicReference<String>("");
110127

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

113130
@Override
114131
public void onMessage(String message) {
@@ -141,7 +158,8 @@ public void onError(Throwable t) {
141158
latch.await();
142159
assertEquals(text.get(), "ECHO");
143160
} finally {
144-
client.close();
161+
asyncHttpClient.close();
145162
}
163+
146164
}
147165
}

0 commit comments

Comments
 (0)