Skip to content

Commit a63b1c7

Browse files
committed
Port changes from master.
- improve proxy tunneling test - Fix proxy tunneling in grizzly provider - add WS tunneling support.
1 parent 477bb3a commit a63b1c7

File tree

3 files changed

+78
-36
lines changed

3 files changed

+78
-36
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@
528528
<dependency>
529529
<groupId>org.glassfish.grizzly</groupId>
530530
<artifactId>grizzly-websockets</artifactId>
531-
<version>2.2.10</version>
531+
<version>2.2.16</version>
532532
<optional>true</optional>
533533
</dependency>
534534
</dependencies>

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

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
import org.glassfish.grizzly.websockets.DataFrame;
102102
import org.glassfish.grizzly.websockets.DefaultWebSocket;
103103
import org.glassfish.grizzly.websockets.HandShake;
104+
import org.glassfish.grizzly.websockets.HandshakeException;
104105
import org.glassfish.grizzly.websockets.ProtocolHandler;
105106
import org.glassfish.grizzly.websockets.Version;
106107
import org.glassfish.grizzly.websockets.WebSocketEngine;
@@ -147,7 +148,7 @@ public class GrizzlyAsyncHttpProvider implements AsyncHttpProvider {
147148
private final static Logger LOGGER = LoggerFactory.getLogger(GrizzlyAsyncHttpProvider.class);
148149
private static final boolean SEND_FILE_SUPPORT;
149150
static {
150-
SEND_FILE_SUPPORT = configSendFileSupport();
151+
SEND_FILE_SUPPORT = /*configSendFileSupport()*/ false;
151152
}
152153
private final Attribute<HttpTransactionContext> REQUEST_STATE_ATTR =
153154
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute(HttpTransactionContext.class.getName());
@@ -619,6 +620,7 @@ final class HttpTransactionContext {
619620
HandShake handshake;
620621
ProtocolHandler protocolHandler;
621622
WebSocket webSocket;
623+
boolean establishingTunnel;
622624

623625

624626
// -------------------------------------------------------- Constructors
@@ -677,6 +679,15 @@ void result(Object result) {
677679
}
678680
}
679681

682+
boolean isTunnelEstablished(final Connection c) {
683+
return c.getAttributes().getAttribute("tunnel-established") != null;
684+
}
685+
686+
687+
void tunnelEstablished(final Connection c) {
688+
c.getAttributes().setAttribute("tunnel-established", Boolean.TRUE);
689+
}
690+
680691

681692
} // END HttpTransactionContext
682693

@@ -844,7 +855,9 @@ private boolean sendAsGrizzlyRequest(final Request request,
844855
final ProxyServer proxy = getProxyServer(request);
845856
final boolean useProxy = (proxy != null);
846857
if (useProxy) {
847-
if (secure) {
858+
if ((secure || httpCtx.isWSRequest) && !httpCtx.isTunnelEstablished(ctx.getConnection())) {
859+
secure = false;
860+
httpCtx.establishingTunnel = true;
848861
builder.method(Method.CONNECT);
849862
builder.uri(AsyncHttpProviderUtils.getAuthority(uri));
850863
} else {
@@ -864,7 +877,7 @@ private boolean sendAsGrizzlyRequest(final Request request,
864877
}
865878

866879
HttpRequestPacket requestPacket;
867-
if (httpCtx.isWSRequest) {
880+
if (httpCtx.isWSRequest && !httpCtx.establishingTunnel) {
868881
try {
869882
final URI wsURI = new URI(httpCtx.wsRequestURI);
870883
httpCtx.protocolHandler = Version.DRAFT17.createHandler(true);
@@ -877,7 +890,10 @@ private boolean sendAsGrizzlyRequest(final Request request,
877890
} else {
878891
requestPacket = builder.build();
879892
}
880-
requestPacket.setSecure(true);
893+
requestPacket.setSecure(secure);
894+
if (secure) {
895+
ctx.notifyDownstream(new SwitchingSSLFilter.SSLSwitchingEvent(true, ctx.getConnection()));
896+
}
881897
if (!useProxy && !httpCtx.isWSRequest) {
882898
addQueryString(request, requestPacket);
883899
}
@@ -1139,14 +1155,19 @@ protected void onInitialLineParsed(HttpHeader httpHeader,
11391155
if (httpHeader.isSkipRemainder()) {
11401156
return;
11411157
}
1158+
final Connection connection = ctx.getConnection();
11421159
final HttpTransactionContext context =
1143-
provider.getHttpTransactionContext(ctx.getConnection());
1160+
provider.getHttpTransactionContext(connection);
11441161
final int status = ((HttpResponsePacket) httpHeader).getStatus();
1162+
if (context.establishingTunnel && HttpStatus.OK_200.statusMatches(status)) {
1163+
return;
1164+
}
11451165
if (HttpStatus.CONINTUE_100.statusMatches(status)) {
11461166
ctx.notifyUpstream(new ContinueEvent(context));
11471167
return;
11481168
}
11491169

1170+
11501171
if (context.statusHandler != null && !context.statusHandler.handlesStatus(status)) {
11511172
context.statusHandler = null;
11521173
context.invocationStatus = StatusHandler.InvocationStatus.CONTINUE;
@@ -1180,9 +1201,9 @@ protected void onInitialLineParsed(HttpHeader httpHeader,
11801201
}
11811202
}
11821203
final GrizzlyResponseStatus responseStatus =
1183-
new GrizzlyResponseStatus((HttpResponsePacket) httpHeader,
1184-
getURI(context.requestUrl),
1185-
provider);
1204+
new GrizzlyResponseStatus((HttpResponsePacket) httpHeader,
1205+
getURI(context.requestUrl),
1206+
provider);
11861207
context.responseStatus = responseStatus;
11871208
if (context.statusHandler != null) {
11881209
return;
@@ -1193,6 +1214,10 @@ protected void onInitialLineParsed(HttpHeader httpHeader,
11931214
final AsyncHandler handler = context.handler;
11941215
if (handler != null) {
11951216
context.currentState = handler.onStatusReceived(responseStatus);
1217+
if (context.isWSRequest && context.currentState == AsyncHandler.STATE.ABORT) {
1218+
httpHeader.setSkipRemainder(true);
1219+
context.abort(new HandshakeException("Upgrade failed"));
1220+
}
11961221
}
11971222
} catch (Exception e) {
11981223
httpHeader.setSkipRemainder(true);
@@ -1221,24 +1246,23 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
12211246
FilterChainContext ctx) {
12221247

12231248
super.onHttpHeadersParsed(httpHeader, ctx);
1224-
if (LOGGER.isDebugEnabled()) {
1225-
LOGGER.debug("RESPONSE: " + httpHeader.toString());
1226-
}
1249+
LOGGER.debug("RESPONSE: {}", httpHeader);
12271250
if (httpHeader.containsHeader(Header.Connection)) {
12281251
if ("close".equals(httpHeader.getHeader(Header.Connection))) {
12291252
ConnectionManager.markConnectionAsDoNotCache(ctx.getConnection());
12301253
}
12311254
}
1232-
if (httpHeader.isSkipRemainder()) {
1233-
return;
1234-
}
12351255
final HttpTransactionContext context =
12361256
provider.getHttpTransactionContext(ctx.getConnection());
1257+
if (httpHeader.isSkipRemainder() || context.establishingTunnel) {
1258+
return;
1259+
}
1260+
12371261
final AsyncHandler handler = context.handler;
12381262
final List<ResponseFilter> filters = context.provider.clientConfig.getResponseFilters();
12391263
final GrizzlyResponseHeaders responseHeaders = new GrizzlyResponseHeaders((HttpResponsePacket) httpHeader,
1240-
null,
1241-
provider);
1264+
null,
1265+
provider);
12421266
if (!filters.isEmpty()) {
12431267
FilterContext fc = new FilterContext.FilterContextBuilder()
12441268
.asyncHandler(handler).request(context.request)
@@ -1260,16 +1284,16 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
12601284
context.provider.connectionManager;
12611285
final Connection c =
12621286
m.obtainConnection(newRequest,
1263-
context.future);
1287+
context.future);
12641288
final HttpTransactionContext newContext =
12651289
context.copy();
12661290
context.future = null;
12671291
provider.setHttpTransactionContext(c, newContext);
12681292
try {
12691293
context.provider.execute(c,
1270-
newRequest,
1271-
newHandler,
1272-
context.future);
1294+
newRequest,
1295+
newHandler,
1296+
context.future);
12731297
} catch (IOException ioe) {
12741298
newContext.abort(ioe);
12751299
}
@@ -1281,8 +1305,8 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
12811305
}
12821306
if (context.statusHandler != null && context.invocationStatus == StatusHandler.InvocationStatus.CONTINUE) {
12831307
final boolean result = context.statusHandler.handleStatus(((HttpResponsePacket) httpHeader),
1284-
context,
1285-
ctx);
1308+
context,
1309+
ctx);
12861310
if (!result) {
12871311
httpHeader.setSkipRemainder(true);
12881312
return;
@@ -1347,20 +1371,38 @@ protected boolean onHttpPacketParsed(HttpHeader httpHeader, FilterChainContext c
13471371

13481372
result = super.onHttpPacketParsed(httpHeader, ctx);
13491373

1350-
final HttpTransactionContext context = cleanup(ctx, provider);
1351-
1352-
final AsyncHandler handler = context.handler;
1353-
if (handler != null) {
1374+
final HttpTransactionContext context = provider.getHttpTransactionContext(ctx.getConnection());
1375+
if (context.establishingTunnel
1376+
&& HttpStatus.OK_200.statusMatches(
1377+
((HttpResponsePacket) httpHeader).getStatus())) {
1378+
context.establishingTunnel = false;
1379+
final Connection c = ctx.getConnection();
1380+
context.tunnelEstablished(c);
13541381
try {
1355-
context.result(handler.onCompleted());
1356-
} catch (Exception e) {
1382+
context.provider.execute(c,
1383+
context.request,
1384+
context.handler,
1385+
context.future);
1386+
return result;
1387+
} catch (IOException e) {
13571388
context.abort(e);
1389+
return result;
13581390
}
13591391
} else {
1360-
context.done(null);
1361-
}
1392+
cleanup(ctx, provider);
1393+
final AsyncHandler handler = context.handler;
1394+
if (handler != null) {
1395+
try {
1396+
context.result(handler.onCompleted());
1397+
} catch (Exception e) {
1398+
context.abort(e);
1399+
}
1400+
} else {
1401+
context.done(null);
1402+
}
13621403

1363-
return result;
1404+
return result;
1405+
}
13641406
}
13651407

13661408

@@ -1389,7 +1431,7 @@ private static HttpTransactionContext cleanup(final FilterChainContext ctx,
13891431
context.abort(new IOException("Maximum pooled connections exceeded"));
13901432
} else {
13911433
if (!context.provider.connectionManager.returnConnection(context.requestUrl, c)) {
1392-
ctx.getConnection().close().markForRecycle(true);
1434+
ctx.getConnection().close();
13931435
}
13941436
}
13951437

src/test/java/com/ning/http/client/async/ProxyyTunnellingTest.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
}
@@ -162,7 +162,7 @@ public void testSimpleAHCConfigProxy() throws IOException, InterruptedException,
162162
Response r = client.get().get();
163163

164164
assertEquals(r.getStatusCode(), 200);
165-
assertEquals(r.getHeader("server"), "Jetty(8.1.1.v20120215)");
165+
assertEquals(r.getHeader("X-Proxy-Connection"), "keep-alive");
166166

167167
client.close();
168168
}

0 commit comments

Comments
 (0)