Skip to content

Commit 3472bc2

Browse files
committed
- improve proxy tunneling test
- Fix proxy tunneling in grizzly provider - add WS tunneling support.
1 parent 49678eb commit 3472bc2

File tree

3 files changed

+62
-23
lines changed

3 files changed

+62
-23
lines changed

api/src/test/java/com/ning/http/client/async/ProxyTunnellingTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public Response onCompleted(Response response) throws Exception {
111111
});
112112
Response r = responseFuture.get();
113113
assertEquals(r.getStatusCode(), 200);
114-
assertEquals(r.getHeader("server"), "Jetty(8.1.1.v20120215)");
114+
assertEquals(r.getHeader("X-Proxy-Connection"), "keep-alive");
115115

116116
asyncHttpClient.close();
117117
}
@@ -142,7 +142,7 @@ public Response onCompleted(Response response) throws Exception {
142142
});
143143
Response r = responseFuture.get();
144144
assertEquals(r.getStatusCode(), 200);
145-
assertEquals(r.getHeader("server"), "Jetty(8.1.1.v20120215)");
145+
assertEquals(r.getHeader("X-Proxy-Connection"), "keep-alive");
146146

147147
asyncHttpClient.close();
148148
}
@@ -161,7 +161,7 @@ public void testSimpleAHCConfigProxy() throws IOException, InterruptedException,
161161
Response r = client.get().get();
162162

163163
assertEquals(r.getStatusCode(), 200);
164-
assertEquals(r.getHeader("server"), "Jetty(8.1.1.v20120215)");
164+
assertEquals(r.getHeader("X-Proxy-Connection"), "keep-alive");
165165

166166
client.close();
167167
}

providers/grizzly/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<dependency>
2121
<groupId>org.glassfish.grizzly</groupId>
2222
<artifactId>grizzly-websockets</artifactId>
23-
<version>2.2.10</version>
23+
<version>2.2.14-SNAPSHOT</version>
2424
</dependency>
2525
<dependency>
2626
<groupId>com.ning</groupId>

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

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public class GrizzlyAsyncHttpProvider implements AsyncHttpProvider {
148148
private final static Logger LOGGER = LoggerFactory.getLogger(GrizzlyAsyncHttpProvider.class);
149149
private static final boolean SEND_FILE_SUPPORT;
150150
static {
151-
SEND_FILE_SUPPORT = configSendFileSupport();
151+
SEND_FILE_SUPPORT = /*configSendFileSupport();*/ false;
152152
}
153153
private final Attribute<HttpTransactionContext> REQUEST_STATE_ATTR =
154154
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute(HttpTransactionContext.class.getName());
@@ -616,6 +616,7 @@ final class HttpTransactionContext {
616616
HandShake handshake;
617617
ProtocolHandler protocolHandler;
618618
WebSocket webSocket;
619+
boolean establishingTunnel;
619620

620621

621622
// -------------------------------------------------------- Constructors
@@ -674,6 +675,15 @@ void result(Object result) {
674675
}
675676
}
676677

678+
boolean isTunnelEstablished(final Connection c) {
679+
return c.getAttributes().getAttribute("tunnel-established") != null;
680+
}
681+
682+
683+
void tunnelEstablished(final Connection c) {
684+
c.getAttributes().setAttribute("tunnel-established", Boolean.TRUE);
685+
}
686+
677687

678688
} // END HttpTransactionContext
679689

@@ -841,7 +851,9 @@ private boolean sendAsGrizzlyRequest(final Request request,
841851
final ProxyServer proxy = getProxyServer(request);
842852
final boolean useProxy = (proxy != null);
843853
if (useProxy) {
844-
if (secure) {
854+
if ((secure || httpCtx.isWSRequest) && !httpCtx.isTunnelEstablished(ctx.getConnection())) {
855+
secure = false;
856+
httpCtx.establishingTunnel = true;
845857
builder.method(Method.CONNECT);
846858
builder.uri(AsyncHttpProviderUtils.getAuthority(uri));
847859
} else {
@@ -861,7 +873,7 @@ private boolean sendAsGrizzlyRequest(final Request request,
861873
}
862874

863875
HttpRequestPacket requestPacket;
864-
if (httpCtx.isWSRequest) {
876+
if (httpCtx.isWSRequest && !httpCtx.establishingTunnel) {
865877
try {
866878
final URI wsURI = new URI(httpCtx.wsRequestURI);
867879
httpCtx.protocolHandler = Version.DRAFT17.createHandler(true);
@@ -874,7 +886,10 @@ private boolean sendAsGrizzlyRequest(final Request request,
874886
} else {
875887
requestPacket = builder.build();
876888
}
877-
requestPacket.setSecure(true);
889+
requestPacket.setSecure(secure);
890+
if (secure) {
891+
ctx.notifyDownstream(new SwitchingSSLFilter.SSLSwitchingEvent(true, ctx.getConnection()));
892+
}
878893
if (!useProxy && !httpCtx.isWSRequest) {
879894
addQueryString(request, requestPacket);
880895
}
@@ -906,7 +921,6 @@ private boolean sendAsGrizzlyRequest(final Request request,
906921

907922
}
908923

909-
910924
private boolean isUpgradeRequest(final AsyncHandler handler) {
911925
return (handler instanceof UpgradeHandler);
912926
}
@@ -1136,14 +1150,19 @@ protected void onInitialLineParsed(HttpHeader httpHeader,
11361150
if (httpHeader.isSkipRemainder()) {
11371151
return;
11381152
}
1153+
final Connection connection = ctx.getConnection();
11391154
final HttpTransactionContext context =
1140-
provider.getHttpTransactionContext(ctx.getConnection());
1155+
provider.getHttpTransactionContext(connection);
11411156
final int status = ((HttpResponsePacket) httpHeader).getStatus();
1157+
if (context.establishingTunnel && HttpStatus.OK_200.statusMatches(status)) {
1158+
return;
1159+
}
11421160
if (HttpStatus.CONINTUE_100.statusMatches(status)) {
11431161
ctx.notifyUpstream(new ContinueEvent(context));
11441162
return;
11451163
}
11461164

1165+
11471166
if (context.statusHandler != null && !context.statusHandler.handlesStatus(status)) {
11481167
context.statusHandler = null;
11491168
context.invocationStatus = StatusHandler.InvocationStatus.CONTINUE;
@@ -1224,11 +1243,12 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
12241243
ConnectionManager.markConnectionAsDoNotCache(ctx.getConnection());
12251244
}
12261245
}
1227-
if (httpHeader.isSkipRemainder()) {
1246+
final HttpTransactionContext context =
1247+
provider.getHttpTransactionContext(ctx.getConnection());
1248+
if (httpHeader.isSkipRemainder() || context.establishingTunnel) {
12281249
return;
12291250
}
1230-
final HttpTransactionContext context =
1231-
provider.getHttpTransactionContext(ctx.getConnection());
1251+
12321252
final AsyncHandler handler = context.handler;
12331253
final List<ResponseFilter> filters = context.provider.clientConfig.getResponseFilters();
12341254
final GrizzlyResponseHeaders responseHeaders = new GrizzlyResponseHeaders((HttpResponsePacket) httpHeader,
@@ -1328,6 +1348,7 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
13281348

13291349
}
13301350

1351+
@SuppressWarnings("unchecked")
13311352
@Override
13321353
protected boolean onHttpPacketParsed(HttpHeader httpHeader, FilterChainContext ctx) {
13331354

@@ -1340,20 +1361,38 @@ protected boolean onHttpPacketParsed(HttpHeader httpHeader, FilterChainContext c
13401361

13411362
result = super.onHttpPacketParsed(httpHeader, ctx);
13421363

1343-
final HttpTransactionContext context = cleanup(ctx, provider);
1344-
1345-
final AsyncHandler handler = context.handler;
1346-
if (handler != null) {
1364+
final HttpTransactionContext context = provider.getHttpTransactionContext(ctx.getConnection());
1365+
if (context.establishingTunnel
1366+
&& HttpStatus.OK_200.statusMatches(
1367+
((HttpResponsePacket) httpHeader).getStatus())) {
1368+
context.establishingTunnel = false;
1369+
final Connection c = ctx.getConnection();
1370+
context.tunnelEstablished(c);
13471371
try {
1348-
context.result(handler.onCompleted());
1349-
} catch (Exception e) {
1372+
context.provider.execute(c,
1373+
context.request,
1374+
context.handler,
1375+
context.future);
1376+
return result;
1377+
} catch (IOException e) {
13501378
context.abort(e);
1379+
return result;
13511380
}
13521381
} else {
1353-
context.done(null);
1354-
}
1382+
cleanup(ctx, provider);
1383+
final AsyncHandler handler = context.handler;
1384+
if (handler != null) {
1385+
try {
1386+
context.result(handler.onCompleted());
1387+
} catch (Exception e) {
1388+
context.abort(e);
1389+
}
1390+
} else {
1391+
context.done(null);
1392+
}
13551393

1356-
return result;
1394+
return result;
1395+
}
13571396
}
13581397

13591398

@@ -1382,7 +1421,7 @@ private static HttpTransactionContext cleanup(final FilterChainContext ctx,
13821421
context.abort(new IOException("Maximum pooled connections exceeded"));
13831422
} else {
13841423
if (!context.provider.connectionManager.returnConnection(context.requestUrl, c)) {
1385-
ctx.getConnection().close().markForRecycle(true);
1424+
ctx.getConnection().close();
13861425
}
13871426
}
13881427

0 commit comments

Comments
 (0)