Skip to content

Commit 21a0fdf

Browse files
jfarcandStephane Landelle
authored andcommitted
Improve fixed for AsyncHttpClient#110. Also fixes AsyncHttpClient#156 by properly invoking the AsyncHandler/WebSocketListener
1 parent 8978a54 commit 21a0fdf

File tree

3 files changed

+147
-94
lines changed

3 files changed

+147
-94
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,12 @@ protected void onInitialLineParsed(HttpHeader httpHeader,
11801180
context.currentState = handler.onStatusReceived(responseStatus);
11811181
if (context.isWSRequest && context.currentState == AsyncHandler.STATE.ABORT) {
11821182
httpHeader.setSkipRemainder(true);
1183-
context.abort(new HandshakeException("Upgrade failed"));
1183+
try {
1184+
context.result(handler.onCompleted());
1185+
context.done();
1186+
} catch (Exception e) {
1187+
context.abort(e);
1188+
}
11841189
}
11851190
}
11861191
} catch (Exception e) {

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

Lines changed: 101 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -15,50 +15,53 @@
1515
*/
1616
package com.ning.http.client.providers.netty;
1717

18-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.BOSS_EXECUTOR_SERVICE;
19-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.DISABLE_NESTED_REQUEST;
20-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.EXECUTE_ASYNC_CONNECT;
21-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTPS_CLIENT_CODEC_MAX_CHUNK_SIZE;
22-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTPS_CLIENT_CODEC_MAX_HEADER_SIZE;
23-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTPS_CLIENT_CODEC_MAX_INITIAL_LINE_LENGTH;
24-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTP_CLIENT_CODEC_MAX_CHUNK_SIZE;
25-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTP_CLIENT_CODEC_MAX_HEADER_SIZE;
26-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTP_CLIENT_CODEC_MAX_INITIAL_LINE_LENGTH;
27-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.REUSE_ADDRESS;
28-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.SOCKET_CHANNEL_FACTORY;
29-
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.USE_BLOCKING_IO;
30-
import static com.ning.http.util.AsyncHttpProviderUtils.DEFAULT_CHARSET;
31-
import static com.ning.http.util.MiscUtil.isNonEmpty;
32-
import static org.jboss.netty.channel.Channels.pipeline;
33-
34-
import java.io.File;
35-
import java.io.FileInputStream;
36-
import java.io.IOException;
37-
import java.io.RandomAccessFile;
38-
import java.net.ConnectException;
39-
import java.net.InetSocketAddress;
40-
import java.net.MalformedURLException;
41-
import java.net.URI;
42-
import java.nio.channels.ClosedChannelException;
43-
import java.nio.channels.FileChannel;
44-
import java.nio.channels.WritableByteChannel;
45-
import java.nio.charset.Charset;
46-
import java.security.GeneralSecurityException;
47-
import java.security.NoSuchAlgorithmException;
48-
import java.util.ArrayList;
49-
import java.util.List;
50-
import java.util.Locale;
51-
import java.util.Map.Entry;
52-
import java.util.concurrent.Callable;
53-
import java.util.concurrent.ExecutorService;
54-
import java.util.concurrent.Executors;
55-
import java.util.concurrent.RejectedExecutionException;
56-
import java.util.concurrent.Semaphore;
57-
import java.util.concurrent.TimeUnit;
58-
import java.util.concurrent.atomic.AtomicBoolean;
59-
60-
import javax.net.ssl.SSLEngine;
61-
18+
import com.ning.http.client.AsyncHandler;
19+
import com.ning.http.client.AsyncHandler.STATE;
20+
import com.ning.http.client.AsyncHandlerExtensions;
21+
import com.ning.http.client.AsyncHttpClientConfig;
22+
import com.ning.http.client.AsyncHttpProvider;
23+
import com.ning.http.client.Body;
24+
import com.ning.http.client.BodyGenerator;
25+
import com.ning.http.client.ConnectionPoolKeyStrategy;
26+
import com.ning.http.client.ConnectionsPool;
27+
import com.ning.http.client.Cookie;
28+
import com.ning.http.client.FluentCaseInsensitiveStringsMap;
29+
import com.ning.http.client.HttpResponseBodyPart;
30+
import com.ning.http.client.HttpResponseHeaders;
31+
import com.ning.http.client.HttpResponseStatus;
32+
import com.ning.http.client.ListenableFuture;
33+
import com.ning.http.client.MaxRedirectException;
34+
import com.ning.http.client.PerRequestConfig;
35+
import com.ning.http.client.ProgressAsyncHandler;
36+
import com.ning.http.client.ProxyServer;
37+
import com.ning.http.client.RandomAccessBody;
38+
import com.ning.http.client.Realm;
39+
import com.ning.http.client.Request;
40+
import com.ning.http.client.RequestBuilder;
41+
import com.ning.http.client.Response;
42+
import com.ning.http.client.filter.FilterContext;
43+
import com.ning.http.client.filter.FilterException;
44+
import com.ning.http.client.filter.IOExceptionFilter;
45+
import com.ning.http.client.filter.ResponseFilter;
46+
import com.ning.http.client.generators.InputStreamBodyGenerator;
47+
import com.ning.http.client.listener.TransferCompletionHandler;
48+
import com.ning.http.client.ntlm.NTLMEngine;
49+
import com.ning.http.client.ntlm.NTLMEngineException;
50+
import com.ning.http.client.providers.netty.spnego.SpnegoEngine;
51+
import com.ning.http.client.providers.netty.timeout.IdleConnectionTimeoutTimerTask;
52+
import com.ning.http.client.providers.netty.timeout.RequestTimeoutTimerTask;
53+
import com.ning.http.client.providers.netty.timeout.TimeoutsHolder;
54+
import com.ning.http.client.websocket.WebSocketUpgradeHandler;
55+
import com.ning.http.multipart.MultipartBody;
56+
import com.ning.http.multipart.MultipartRequestEntity;
57+
import com.ning.http.util.AsyncHttpProviderUtils;
58+
import com.ning.http.util.AuthenticatorUtils;
59+
import com.ning.http.util.CleanupChannelGroup;
60+
import com.ning.http.util.ProxyUtils;
61+
import com.ning.http.util.SslUtils;
62+
import com.ning.http.util.UTF8UrlEncoder;
63+
import com.ning.org.jboss.netty.handler.codec.http.CookieDecoder;
64+
import com.ning.org.jboss.netty.handler.codec.http.CookieEncoder;
6265
import org.jboss.netty.bootstrap.ClientBootstrap;
6366
import org.jboss.netty.buffer.ChannelBuffer;
6467
import org.jboss.netty.buffer.ChannelBufferOutputStream;
@@ -108,53 +111,48 @@
108111
import org.slf4j.Logger;
109112
import org.slf4j.LoggerFactory;
110113

111-
import com.ning.http.client.AsyncHandler;
112-
import com.ning.http.client.AsyncHandler.STATE;
113-
import com.ning.http.client.AsyncHandlerExtensions;
114-
import com.ning.http.client.AsyncHttpClientConfig;
115-
import com.ning.http.client.AsyncHttpProvider;
116-
import com.ning.http.client.Body;
117-
import com.ning.http.client.BodyGenerator;
118-
import com.ning.http.client.ConnectionPoolKeyStrategy;
119-
import com.ning.http.client.ConnectionsPool;
120-
import com.ning.http.client.Cookie;
121-
import com.ning.http.client.FluentCaseInsensitiveStringsMap;
122-
import com.ning.http.client.HttpResponseBodyPart;
123-
import com.ning.http.client.HttpResponseHeaders;
124-
import com.ning.http.client.HttpResponseStatus;
125-
import com.ning.http.client.ListenableFuture;
126-
import com.ning.http.client.MaxRedirectException;
127-
import com.ning.http.client.PerRequestConfig;
128-
import com.ning.http.client.ProgressAsyncHandler;
129-
import com.ning.http.client.ProxyServer;
130-
import com.ning.http.client.RandomAccessBody;
131-
import com.ning.http.client.Realm;
132-
import com.ning.http.client.Request;
133-
import com.ning.http.client.RequestBuilder;
134-
import com.ning.http.client.Response;
135-
import com.ning.http.client.filter.FilterContext;
136-
import com.ning.http.client.filter.FilterException;
137-
import com.ning.http.client.filter.IOExceptionFilter;
138-
import com.ning.http.client.filter.ResponseFilter;
139-
import com.ning.http.client.generators.InputStreamBodyGenerator;
140-
import com.ning.http.client.listener.TransferCompletionHandler;
141-
import com.ning.http.client.ntlm.NTLMEngine;
142-
import com.ning.http.client.ntlm.NTLMEngineException;
143-
import com.ning.http.client.providers.netty.spnego.SpnegoEngine;
144-
import com.ning.http.client.providers.netty.timeout.IdleConnectionTimeoutTimerTask;
145-
import com.ning.http.client.providers.netty.timeout.RequestTimeoutTimerTask;
146-
import com.ning.http.client.providers.netty.timeout.TimeoutsHolder;
147-
import com.ning.http.client.websocket.WebSocketUpgradeHandler;
148-
import com.ning.http.multipart.MultipartBody;
149-
import com.ning.http.multipart.MultipartRequestEntity;
150-
import com.ning.http.util.AsyncHttpProviderUtils;
151-
import com.ning.http.util.AuthenticatorUtils;
152-
import com.ning.http.util.CleanupChannelGroup;
153-
import com.ning.http.util.ProxyUtils;
154-
import com.ning.http.util.SslUtils;
155-
import com.ning.http.util.UTF8UrlEncoder;
156-
import com.ning.org.jboss.netty.handler.codec.http.CookieDecoder;
157-
import com.ning.org.jboss.netty.handler.codec.http.CookieEncoder;
114+
import javax.net.ssl.SSLEngine;
115+
import java.io.File;
116+
import java.io.FileInputStream;
117+
import java.io.IOException;
118+
import java.io.RandomAccessFile;
119+
import java.net.ConnectException;
120+
import java.net.InetSocketAddress;
121+
import java.net.MalformedURLException;
122+
import java.net.URI;
123+
import java.nio.channels.ClosedChannelException;
124+
import java.nio.channels.FileChannel;
125+
import java.nio.channels.WritableByteChannel;
126+
import java.nio.charset.Charset;
127+
import java.security.GeneralSecurityException;
128+
import java.security.NoSuchAlgorithmException;
129+
import java.util.ArrayList;
130+
import java.util.List;
131+
import java.util.Locale;
132+
import java.util.Map.Entry;
133+
import java.util.concurrent.Callable;
134+
import java.util.concurrent.ExecutorService;
135+
import java.util.concurrent.Executors;
136+
import java.util.concurrent.RejectedExecutionException;
137+
import java.util.concurrent.Semaphore;
138+
import java.util.concurrent.TimeUnit;
139+
import java.util.concurrent.atomic.AtomicBoolean;
140+
141+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.BOSS_EXECUTOR_SERVICE;
142+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.DISABLE_NESTED_REQUEST;
143+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.EXECUTE_ASYNC_CONNECT;
144+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTPS_CLIENT_CODEC_MAX_CHUNK_SIZE;
145+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTPS_CLIENT_CODEC_MAX_HEADER_SIZE;
146+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTPS_CLIENT_CODEC_MAX_INITIAL_LINE_LENGTH;
147+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTP_CLIENT_CODEC_MAX_CHUNK_SIZE;
148+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTP_CLIENT_CODEC_MAX_HEADER_SIZE;
149+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.HTTP_CLIENT_CODEC_MAX_INITIAL_LINE_LENGTH;
150+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.REUSE_ADDRESS;
151+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.SOCKET_CHANNEL_FACTORY;
152+
import static com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig.USE_BLOCKING_IO;
153+
import static com.ning.http.util.AsyncHttpProviderUtils.DEFAULT_CHARSET;
154+
import static com.ning.http.util.MiscUtil.isNonEmpty;
155+
import static org.jboss.netty.channel.Channels.pipeline;
158156

159157
public class NettyAsyncHttpProvider extends SimpleChannelUpstreamHandler implements AsyncHttpProvider {
160158

@@ -2279,16 +2277,26 @@ public void handle(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
22792277
s = new ResponseStatus(future.getURI(), response, NettyAsyncHttpProvider.this);
22802278
final boolean statusReceived = h.onStatusReceived(s) == STATE.UPGRADE;
22812279

2280+
if (!statusReceived) {
2281+
try {
2282+
h.onCompleted();
2283+
} finally {
2284+
future.done();
2285+
}
2286+
return;
2287+
}
2288+
22822289
final boolean headerOK = h.onHeadersReceived(responseHeaders) == STATE.CONTINUE;
2283-
if (!headerOK || !validStatus || !validUpgrade || !validConnection || !statusReceived) {
2290+
if (!headerOK || !validStatus || !validUpgrade || !validConnection) {
22842291
abort(future, new IOException("Invalid handshake response"));
22852292
return;
22862293
}
22872294

22882295
String accept = response.getHeader(HttpHeaders.Names.SEC_WEBSOCKET_ACCEPT);
22892296
String key = WebSocketUtil.getAcceptKey(future.getNettyRequest().getHeader(HttpHeaders.Names.SEC_WEBSOCKET_KEY));
22902297
if (accept == null || !accept.equals(key)) {
2291-
throw new IOException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, key));
2298+
abort(future, new IOException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, key)));
2299+
return;
22922300
}
22932301

22942302
ctx.getPipeline().replace("http-encoder", "ws-encoder", new WebSocket08FrameEncoder(true));

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,44 @@ public void onError(Throwable t) {
133133
c.close();
134134
}
135135
}
136+
137+
@Test(timeOut = 60000)
138+
public void wrongProtocolCode() throws Throwable {
139+
AsyncHttpClient c = getAsyncHttpClient(null);
140+
try {
141+
final CountDownLatch latch = new CountDownLatch(1);
142+
final AtomicReference<Throwable> throwable = new AtomicReference<Throwable>();
143+
144+
WebSocket websocket = c.prepareGet("ws://www.google.com/").execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(new WebSocketTextListener() {
145+
146+
@Override
147+
public void onMessage(String message) {
148+
}
149+
150+
@Override
151+
public void onFragment(String fragment, boolean last) {
152+
}
153+
154+
@Override
155+
public void onOpen(com.ning.http.client.websocket.WebSocket websocket) {
156+
}
157+
158+
@Override
159+
public void onClose(com.ning.http.client.websocket.WebSocket websocket) {
160+
}
161+
162+
@Override
163+
public void onError(Throwable t) {
164+
throwable.set(t);
165+
latch.countDown();
166+
}
167+
}).build()).get();
168+
169+
latch.await();
170+
assertNotNull(throwable.get());
171+
assertEquals(throwable.get().getClass(), IllegalStateException.class);
172+
} finally {
173+
c.close();
174+
}
175+
}
136176
}

0 commit comments

Comments
 (0)