Apache HTTP Client 4.3.4 Example with Timeouts, Client Cert and Trusted Cert from KeyStores

If you have ever used or tried to use the Apache HTTP Client library, you’ve probably discovered that is is very useful and powerful, but they change the library so much each version that it is hard to find proper examples of how to do complex things like adding connection timeouts, basic auth, or adding a client cert, or trusting a self-signed cert. Here’s a code snippet of getting a client cert and a trusted server cert loaded with timeouts in version 4.3.4 of the library.

    <dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.3.4</version>
    </dependency>

    public static HttpClient getSSLClient(String serverKeystoreFile, String serverKeystorePassword, String serverKeystoreType,
                                         String clientCertFile, String clientCertPassword, String clientKeystoreType) throws Exception {

        // Server cert trust stuff
        KeyStore trustStore = KeyStore.getInstance(serverKeystoreType);
        trustStore.load(new FileInputStream(new File(serverKeystoreFile)), serverKeystorePassword.toCharArray());
        TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(trustStore);
        TrustManager[] trustManagers = trustFactory.getTrustManagers();

        // Client cert stuff
        KeyStore clientCert = KeyStore.getInstance(clientKeystoreType);
        clientCert.load(new FileInputStream(new File(clientCertFile)), clientCertPassword.toCharArray());
        KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyFactory.init(clientCert, clientCertPassword.toCharArray());
        KeyManager[] keyManagers = keyFactory.getKeyManagers();

        SSLContext sslcontext = SSLContext.getInstance("TLS");
        sslcontext.init(keyManagers, trustManagers, new SecureRandom());

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext);

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

        return httpClient;
    }

    public static String executePost() throws Exception {

	 URI uri = new URIBuilder("http://my.superawesome.fakeurlstuffandstuff.com/path1/path2/file.php")).build();
	 String serverKeystore = Properties.get("TRUSTED_CERT_KEYSTORE_FILE_PATH"); // JKS FILE
	 String serverPass = Properties.get("TRUSTED_CERT_KEYSTORE_PASSWORD");
	 String clientKeystore = Properties.get("CLIENT_KEYSTORE"); // PFX FILE
	 String clientPass = Properties.get("CLIENT_KEYSTORE_PASSWORD");

	 HttpClient client = HttpJsonUtil.getClient(serverKeystore, serverPass, "JKS", clientKeystore, clientPass, "PKCS12");

	 RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
	 requestConfigBuilder.setMaxRedirects(2);
	 requestConfigBuilder.setConnectionRequestTimeout(Properties.getInt("SERVER_REQUEST_TIMEOUT_MILLIS", 30_000));
	 requestConfigBuilder.setConnectTimeout(Properties.getInt("SERVER_CONNECT_TIMEOUT_MILLIS", 10_000));

	 httpPost = new HttpPost(uri);
	 httpPost.setConfig(requestConfigBuilder.build());
	 httpPost.setEntity(new StringEntity("REQUEST BODY"));
	 httpPost.setHeader("Content-Type", "application/json");
	 httpPost.setHeader("Accept", "application/json");
	 HttpResponse response = client.execute(httpPost);
	 return EntityUtils.toString(response.getEntity());       
    }

Advertisements

Image Proxy using Jersey and HttpClient

Here’s the Jersey Endpoint:

    @GET
    @Path("imageproxy")
    @Produces("image/png")
    public Response imageproxy(@QueryParam("url") String url) {
        byte[] result = null;
        try {
             result = ImageHelper.getUrlBinary(url);
        } catch(Exception ex) {
            logger.error("Error proxying image", ex);
        }
        if(result != null) {
            return Response.ok(new ByteArrayInputStream(result)).build();
        } else {
            return Response.noContent().build();
        }
    }

Here’s the HttpClient code:

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import java.net.URI;

public class ImageHelper {
    private static Logger logger = Logger.getLogger(ImageHelper.class);
    public static byte[] getUrlBinary(String url) {
        byte[] result = null;
        try {
            URI uri = new URI(url);
            HttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(uri);
            HttpResponse response = client.execute(httpGet);
            result = IOUtils.toByteArray(response.getEntity().getContent());
        } catch(Exception ex) {
            logger.error("Error getting binary from: " + url, ex);
        }
        return result;
    }
}