1

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.

Naman
  • 27,789
  • 26
  • 218
  • 353
Marged
  • 10,577
  • 10
  • 57
  • 99

1 Answers1

4

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.

Marged
  • 10,577
  • 10
  • 57
  • 99