Dmitry Potapov created HTTPASYNC-67:
---------------------------------------
Summary: NPE on premature response from server
Key: HTTPASYNC-67
URL: https://issues.apache.org/jira/browse/HTTPASYNC-67
Project: HttpComponents HttpAsyncClient
Issue Type: Improvement
Affects Versions: 4.0 Final
Environment: Linux 3.10.25-gentoo
Reporter: Dmitry Potapov
Priority: Minor
Steps to reproduce:
1. Bind server socket
2. Create CloseableHttpAsyncClient with .setDefaultMaxPerRoute(1);
3. Send two GET requests to port, store each Future<HttpResponse> somewhere
4. Sleep 100 ms (don't know why, but issues is not reproducible without this
sleep)
5. On server socket accept incoming connection and write "HTTP/1.1 200
OK\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" to socket three times
6. Call .get() on both Futures from step 3.
Expected result:
Both .get()s returns valid HttpResponse with status code 200.
or
First .get() throws exception indicating protocol violation (as Content-Length
is 0)
Actual result:
First .get() returns HttpResponse with status code 200.
Second .get() throws java.util.concurrent.ExecutionException:
java.lang.NullPointerException
at org.apache.http.concurrent.BasicFuture.getResult(BasicFuture.java:70)
at org.apache.http.concurrent.BasicFuture.get(BasicFuture.java:80)
at NPETest.main(NPETest.java:46)
Caused by: java.lang.NullPointerException
at
org.apache.http.impl.nio.client.MainClientExec.responseReceived(MainClientExec.java:318)
at
org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseReceived(DefaultClientExchangeHandlerImpl.java:148)
at
org.apache.http.nio.protocol.HttpAsyncRequestExecutor.responseReceived(HttpAsyncRequestExecutor.java:227)
at
org.apache.http.impl.nio.client.LoggingAsyncRequestExecutor.responseReceived(LoggingAsyncRequestExecutor.java:112)
at
org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:256)
at
org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:73)
at
org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:37)
at
org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:116)
at
org.apache.http.impl.nio.reactor.BaseIOReactor.validate(BaseIOReactor.java:219)
at
org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:282)
at
org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
at
org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:589)
at java.lang.Thread.run(Thread.java:744)
NPE is not too informative and probably there should be IOException or
HttpException instead. Most probably this error occurs because no events comes
to reactor after first response consumption.
Here the simple program illustrating the issue:
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
public class NPETest {
public static void main(final String... args) throws Exception {
ServerSocket server = new ServerSocket(0, 1);
PoolingNHttpClientConnectionManager connManager =
new PoolingNHttpClientConnectionManager(
new DefaultConnectingIOReactor());
connManager.setDefaultMaxPerRoute(1);
connManager.setMaxTotal(Integer.MAX_VALUE);
try (CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setConnectionManager(connManager)
.build())
{
client.start();
List<Future<HttpResponse>> requests = new ArrayList<>();
for (int i = 0; i < 2; ++i) {
requests.add(client.execute(
new HttpGet("http://localhost:" + server.getLocalPort()),
null));
}
Socket socket = server.accept();
System.out.println(
System.currentTimeMillis() + " Accepted");
Thread.sleep(100);
for (int i = 0; i < 3; ++i) {
socket.getOutputStream().write(("HTTP/1.1 200 OK\r\n"
+ "Content-Length: 0\r\nConnection: keep-alive\r\n\r\n")
.getBytes(StandardCharsets.UTF_8));
}
for (Future<HttpResponse> request: requests) {
System.out.println("Response: " + request.get());
}
}
}
}
--
This message was sent by Atlassian JIRA
(v6.1.5#6160)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]