title: Java HttpRequest timeout unexpectedly throwing HttpConnectTimeoutException
body: <p>Using the new <code>java.net.http</code> package released with JDK 11, an <code>HttpRequest</code> has been assembled with a deliberately low response timeout:</p>
  
  <pre><code>HttpRequest.Builder builder = HttpRequest.newBuilder(getEndpointUri());
  addRequestHeaders(builder);
  builder.POST(HttpRequest.BodyPublishers.ofString(rawXml));
  builder.timeout(Duration.ofMillis(1));
  HttpRequest httpRequest = builder.build();
  </code></pre>
  
  <p>The aim is to test that <code>HttpTimeoutException</code> outcomes are handled correctly, but unexpectedly this response timeout value is leading to an <code>HttpConnectionTimeoutException</code>, which is being caught by this code:</p>
  
  <pre><code>try {
      HttpResponse&lt;InputStream&gt; httpResponse = completableExchange.join();
  } catch (CompletionException ce) {
      if (ce.getCause() instanceof HttpConnectTimeoutException) {
          System.out.println("Connection timeout occurred!");
      } else {
          throw ce;
      }
  }
  </code></pre>
  
  <p>This means that a response timeout is causing the code to act as though a <strong>connection timeout</strong> has occurred. To the best of my understanding, the connection timeout and response timeout should be separate concepts, which should be possible to catch and handle separately.</p>
  
  <p>The stack trace attached to the <code>HttpConnectionTimeoutException</code> looks like this:</p>
  
  <pre><code>java.net.http.HttpConnectTimeoutException: HTTP connect timed out
      at java.net.http/jdk.internal.net.http.ResponseTimerEvent.handle(ResponseTimerEvent.java:68)
      at java.net.http/jdk.internal.net.http.HttpClientImpl.purgeTimeoutsAndReturnNextDeadline(HttpClientImpl.java:1248)
      at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:877)
  Caused by: java.net.ConnectException: HTTP connect timed out
      at java.net.http/jdk.internal.net.http.ResponseTimerEvent.handle(ResponseTimerEvent.java:69)
      ... 2 more
  </code></pre>
  
  <p>Am I misunderstanding the timeout concepts? Does the <code>HttpRequest</code> timeout value simply provide an alternative to the default of the <code>HttpClient</code> timeout value? Is there a reliable way to catch connection and response timeout as distinct events?</p>
  
  <p>For what it's worth, the Javadoc for <code>HttpRequest.Builder.timeout(Duration)</code> says the following:</p>
  
  <blockquote>
    <p>Sets a timeout for this request. If the response is not received within the specified timeout then an HttpTimeoutException is thrown from HttpClient::send or HttpClient::sendAsync completes exceptionally with an HttpTimeoutException. The effect of not setting a timeout is the same as setting an infinite Duration, ie. block forever.</p>
  </blockquote>
  
  <p>To make things confusing, <code>HttpConnectionTimeoutException</code> is a subclass of <code>HttpTimeoutException</code> so technically the contract of the <code>timeout(Duration)</code> method is being satisfied. But this seems unhelpful.</p>
  
  <p>(Before you ask: yes, the value passed to <code>HttpRequest.Builder.timeout(Duration)</code> is the deciding factor in whether or not an exception is thrown. So the exception is not based on the connection timeout value being used to create the <code>HttpClient</code> instance.)</p>