Search code examples
javaspringhttpclientkeep-alive

Is keep-alive always sent in requests using httpclient and how to prevent sending it


I have a Java/Spring project where I am using Oauth2RestTemplate and making it use HttpClient (org.apache.http.client.Httpclient) instead of the default SimpleClient

HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build(); 

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
oAuth2RestTemplate.setRequestFactory(requestFactory);

With respect to this, I wanted to know/understand if the keep-alive header is always sent for all the requests?

If it is always sent, is there a way to disable sending it? I see a post - Disable Keep Alive in Apache HttpClient that talks about disabling it but it proposes a setting on httpMethod. I am not sure how to get access to this httpMethod in my code setup I described above.


Solution

  • Implement a ConnectionReuseStrategy with a keepAlive() method that simply returns false. See setConnectionReuseStrategy() in HttpClientBuilder.

    You may also want to send a Connection header with the value of close.

    https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/ConnectionReuseStrategy.html

    Example:

    List<Header> headers = new ArrayList<>();
    headers.add(new BasicHeader(HttpHeaders.CONNECTION, "close"));
    HttpClientBuilder builder = HttpClients.custom().setDefaultHeaders(headers)
      .setConnectionReuseStrategy(
        new ConnectionReuseStrategy() {
          @Override
          public boolean keepAlive(HttpResponse httpResponse, HttpContext httpContext) {
            log.info("**** keepAlive strategy returning false");
            return false;
          }
    });
    CloseableHttpClient httpClient = builder.build();
    HttpGet httpGet = new HttpGet("https://google.com");
    CloseableHttpResponse response = httpClient.execute(httpGet);
    log.info("Response status: " + response.getStatusLine());
    response.close();
    

    Some additional information:

    1. The Keep-Alive header

    When most people say keep-alive header, they usually mean a different header called Connection. The two headers work together:

    HTTP/1.1 200 OK
    ...
    Connection: Keep-Alive
    Keep-Alive: timeout=5, max=1000
    ...
    

    The Connection header is a hint that the connection should be re-used. The Keep-Alive header specifies the minimum amount of time the connection should remain open, and the maximum number of requests the connection may be re-used for.

    Common values for the Connection header are keep-alive and close. Both the server and the client can send this header. If the Connection header is set to close, the Keep-Alive header is ignored.

    2. HTTP/1.1 and HTTP/2

    With HTTP/1.1, connections are persistent by default. The Keep-Alive header was deprecated (no longer defined in the HTTP specification), although many servers still send them for backwards compatibility.

    Clients which cannot handle HTTP/1.1 persistent connections should set a Connection header with the value close.

    HTTP/2 uses multiplexing; neither the Connection nor the Keep-Alive header should be used with HTTP/2.

    3. Effect of proxies and caches

    Generally speaking, persistent connections do not work through non-transparent proxies. They will silently drop any Connection or Keep-Alive headers.

    4. Connection handling

    Since persistent connections are now the default with HTTP/1.1, we need a mechanism to control when/how they are used. With the Apache http client, the ConnectionReuseStrategy determines whether or not the connection should be persistent, while the ConnectionKeepAliveStrategy specifies the maximum idle time for a connection to be re-usable.