HttpClient hits timeout but server is available and working flawlessly

2.1k Views Asked by At

My problem is that the HttpClient never makes its way to the target. The target is on the same network (so I need no proxy) and it is definitely up. And the timeout was set quite high (120 seconds), the server is able to respond in less than a second. Using other applications or curl everything works fine.

This is my code, I tried two ways of setting the credentials, they are marked with comments. During my tests I enabled first one then the other:

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI( "https://target:8443/foo/bar"))
    .version(HttpClient.Version.HTTP_1_1)
    // approach 1:
    .header("Authorization", basicAuth("foo", "bar"))
    .timeout(Duration.ofSeconds(120)).POST(HttpRequest.BodyPublishers.ofFile(tempFile.toPath())).build();

HttpResponse<String> response = HttpClient.newBuilder()
    /* approach 2:
    .authenticator(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            System.err.println("Was asked for a password");
            return new PasswordAuthentication("foo", "bar".toCharArray());
        }
    })
    */
    .followRedirects(HttpClient.Redirect.ALWAYS)
    .build()
    .send(request, HttpResponse.BodyHandlers.ofString());
                
                

In contrast this one works:

curl -u foo:bar -X POST -H "content-type: application/vnd.lucidworks-document" https://target:8443/foo/bar --data-binary @test.json -v

My Java code throws this error:

2021-04-25 10:26:56.730 INFO 12316 --- [SelectorManager] jdk.httpclient.HttpClient               CHANNEL: Read error signalled on channel java.nio.channels.SocketChannel[closed]: java.io.IOException: connection closed locally
    at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:561)
    at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:119)
...
Caused by: java.net.ConnectException: Connection timed out: no further information
    at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:779)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection$ConnectEvent.handle(PlainHttpConnection.java:128)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.handleEvent(HttpClientImpl.java:957)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.lambda$run$3(HttpClientImpl.java:912)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:912)

The enabled logs don't show much, but this line makes me think that perhaps the authentication doesn't work and because of this the connection gets "stuck" ?!?

MISC: Applying jdk.internal.net.http.AuthenticationFilter@43b3184

I'm aware that there are version of Java that have the problem I describe but I tried this on current versions of AdoptOpenJDK Java 11 (11.0.11+9) and 15 (15.0.2+7) and still experience the same.

1

There are 1 best solutions below

0
On

Like so often, the reason was dead simple:

The target server only has an IPv4 address. Java for some reason tries to access the target using IPv6 and fails to do so. I assume that this kind of "halts" the ongoing process and this can only be remedied by aborting the hanging thread (what the timeout effectively does)

As soon as I addded -Djava.net.preferIPv4Stack=true to the call of my program, I was able to run it successfully.