The paper

Apache HttpClient 4 starts today with a comprehensive guide to Apache HttpClient 4, from basic to advanced.

Status code

Derive the status code from the Http response

After sending the Http request – we’ll return a org. Apache. Http. HttpResponse instance, we can get to the response status line, and implicitly to access a status code:

response.getStatusLine().getStatusCode()
Copy the code

Using it, we can verify that the code received from the server is correct:

@Test
public void test() 
  throws ClientProtocolException, IOException {
    HttpClient client = HttpClientBuilder.create().build();    
    HttpResponse response = client.execute(new HttpGet(SAMPLE_URL));
    int statusCode = response.getStatusLine().getStatusCode();
    assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
Copy the code

Inside this, use the org. Apache. HTTP. HttpStatus libraries provide predefined status code.

timeout

HttpClient can configure the timeout duration, so let’s see how to use it.

Configure timeout with the string parameter

HttpClient comes with a large number of configuration parameters, all of which can be set in a generic Map set.

There are three timeout parameter configurations:

DefaultHttpClient httpClient = new DefaultHttpClient();
 
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));
Copy the code

Configure the timeout through the API

The more important of these parameters – the first two – can also be set via a more secure API:

DefaultHttpClient httpClient = new DefaultHttpClient();
 
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout
Copy the code

The third parameter has no custom setter in HttpConnectionParams and still needs to be set manually with the setParameter method.

Use the new 4.3 Configuring Timeout

4.3 introduced a new API to set the timeout method, which is easier and faster:

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = 
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();
Copy the code

This is the recommended way to configure all three timeouts in a type-safe and readable manner.

Timeout Attribute Description

Now, let’s explain what these different types of timeouts mean:

  • Connection Timeout (http.connection.timeout) – The time to establish a connection to the remote host
  • Socket Timeout (http.socket.timeout) – The time to wait for data – after the connection is established; Maximum time of inactivity between two packets
  • Connection manager Timeout (http.connection-manager.timeout) – The wait time to get a connection from the connection manager/pool.

The first two parameters, Connection and socket timeout, are the most important. However, it is important to set the timeout for obtaining connections under high load conditions, which is why the third parameter should not be ignored.

Mandatory timeout

While it is useful to set timeouts for establishing HTTP connections and not receiving data, sometimes we need to set mandatory timeouts for the entire request.

For example, perhaps downloads of large files fit this category. In this case, the connection can be established successfully and the data can go through all the time, but we still need to ensure that the operation does not exceed a certain time threshold.

HttpClient does not have any configuration that allows us to set total timeouts for requests; However, it does provide abort functionality for requests, so we can use this mechanism to implement a simple timeout mechanism:


HttpGet getMethod =new HttpGet("http://localhost:8080/");


int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if(getMethod ! = null) { getMethod.abort(); }}}; new Timer(true).schedule(task, hardTimeout * 1000);
 
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());
Copy the code

We are using java.util.Timer and java.util.TimerTask to set up a simple delay task that aborts HTTP GET requests after a 5 second mandatory timeout.

DNS loop Timeout

It is common for some larger domain names to be configured using a DNS loop, essentially having the same domain name mapped to multiple IP addresses. This raises a new challenge for timeouts for such fields, simply because HttpClient will attempt to connect to the timeout fields:

HttpClient gets the list of IP routes for the domain and it tries the first – times out it tries the second – also times out and so on… So, as you can see – when we expect it, the overall operation does not time out. Conversely – it will time out when all possible routes time out. More importantly – this happens completely transparently on the client side (unless you configure logging at the DEBUG level).

Here’s a simple example of how you can run and replicate this problem:

int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
  .setDefaultRequestConfig(config).build();

HttpGet request =new  HttpGet("http://www.domain.com");

 response = client.execute(request);
Copy the code

You will notice retry logic with DEBUG log level:

The DEBUG O.A.H.I.C.H ttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.212:81 the DEBUG O.A.H.I.C.H ttpClientConnectionOperator - Connect to www.domain.com/173.194.34.212:81 timed out. The Connection will be retried using another IP address DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.208:81 the DEBUG O.A.H.I.C.H ttpClientConnectionOperator - Connect to www.domain.com/173.194.34.208:81 timed out. The Connection will be retried using another IP address the DEBUG O.A.H.I.C.H ttpClientConnectionOperator DEBUG - Connecting to www.domain.com/173.194.34.209:81 O.A.H.I.C.H ttpClientConnectionOperator - Connect to www.domain.com/173.194.34.209:81 timed out. The Connection will be retried using another IP address //...Copy the code

summary

This article describes the configuration and mechanism of status codes and timeouts.