title: Connections leaking with state CLOSE_WAIT with HttpClient
body: <p>We are using JDK11 <code>java.net.http</code> HTTP client to get data from an API. After we receive the response the connections remain opened in our server with TCP state <code>CLOSE_WAIT</code>, which means the client must close the connection.</p>
  <p>From <a href="https://www.rfc-editor.org/rfc/rfc793#section-3.2" rel="nofollow noreferrer">RFC 793</a> terminology:</p>
  <blockquote>
  <p>CLOSE-WAIT - represents waiting for a connection termination request
  from the local user.</p>
  </blockquote>
  <p>This is our client code which runs on WildFly 16 running on Java 12 as a stateless REST API. We don't understand why this is happening.</p>
  <pre><code>import java.io.PrintWriter;
  import java.net.ServerSocket;
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpClient.Version;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.net.http.HttpResponse.BodyHandlers;
  
  public class SocketSandbox {
  
      public static void main(String[] args) throws Exception {
          HttpClient client = HttpClient.newBuilder().version(Version.HTTP_1_1).build();
          try (var listener = new ServerSocket(59090)) {
              System.out.println(&quot;Server is running...&quot;);
              while (true) {
                  try (var socket = listener.accept()) {
                      HttpRequest request = HttpRequest
                              .newBuilder(URI.create(&quot;&lt;remote_URL&gt;&quot;))
                              .header(&quot;content-type&quot;, &quot;application/json&quot;).build();
                      HttpResponse&lt;String&gt; response = client.send(request, BodyHandlers.ofString());
                      var out = new PrintWriter(socket.getOutputStream(), true);
                      out.println(String.format(&quot;Response HTTP status: %s&quot;, response.statusCode()));
                  }
              }
          }
      }
  
  }
  </code></pre>
  <p>We get the &quot;status code&quot; meaning the http response was processed.</p>
  <p>When using the same code to call other endpoints connections are fine. It seems to be a particular issue with the remote API we are calling, but still we don't understand why the Java HTTP client is keeping connections opened.</p>
  <p>We tried both Windows and Linux machines, and even standalone outside of WildfFly, but the same result happens. After each request, even doing it from our stateless client and receiving the response, each one is left as <code>CLOSE_WAIT</code> and never close.</p>
  <p>Connections will disappear if we shutdown the Java process.</p>
  <p><a href="https://i.stack.imgur.com/ySwBp.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ySwBp.png" alt="enter image description here" /></a></p>
  <p>Headers that are sent by the HTTP client:</p>
  <pre><code>connection: 'Upgrade, HTTP2-Settings','content-length': '0',
  host: 'localhost:3000', 'http2-settings': 'AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA',
  upgrade: 'h2c',
  user-agent': 'Java-http-client/12'
  </code></pre>
  <p>Server returns response with header: <code>Connection: close</code></p>
  <h2>Update (1)</h2>
  <p>We tried to fine-tune the pool parameters in implementation class <code>jdk.internal.net.http.ConnectionPool</code>.</p>
  <p>It did not solve the problem.</p>
  <pre><code>System.setProperty(&quot;jdk.httpclient.keepalive.timeout&quot;, &quot;5&quot;); // seconds
  System.setProperty(&quot;jdk.httpclient.connectionPoolSize&quot;, &quot;1&quot;);
  </code></pre>
  <h2>Update (2)</h2>
  <p>With <strong>Apache HTTP</strong> the connections l getting left in CLOSE_WAIT state for about 90 seconds, but it is able to the connections after that time.</p>
  <p>Calling method <code>HttpGet.releaseConnection()</code> force the connection close immediately.</p>
  <pre><code>HttpClient client = HttpClients.createDefault();
  HttpGet get = new HttpGet(&quot;https://&lt;placeholderdomain&gt;/api/incidents/list&quot;);
  get.addHeader(&quot;content-type&quot;, &quot;application/json&quot;);
  HttpResponse response = client.execute(get);
  
  // This right here did the trick
  get.releaseConnection();
  
  return response.getStatusLine().getStatusCode();
  </code></pre>
  <p>And with <strong>OkHttp</strong> client it worked as expected out of the box, no connections stuck.</p>
  <pre><code>OkHttpClient client = new OkHttpClient();
  Request request = new Request.Builder()
          .url(&quot;https://&lt;placeholderdomain&gt;/grb/sb/incidentes/listar&quot;)
          .header(&quot;content-type&quot;, &quot;application/json&quot;).build();
  Response response = client.newCall(request).execute();
  return response.body().string();
  </code></pre>
  <p>We are still trying to find how to make it work in java-http-client so that we don't have to rewrite the code.</p>