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]

Reply via email to