Tuesday, February 21, 2017

Using Apache HttpClient Fluent API

The Apache HttpClient provides reach functionality and flexibility for implementing of HTTP client java applications.
The Fluent API is an easy facade to the basic HttpClient functionality. It may be quite sufficient for simple applications, which should not deal with connection management, resources allocation or other advance stuff. The fluent API concept is designed to call methods in chain, which makes code rather compact and intuitive.

Dependencies


HttpClient Fluent API maven dependencies:
 <dependency>  
      <groupId>org.apache.httpcomponents</groupId>  
      <artifactId>fluent-hc</artifactId>  
      <version>4.5.1</version>  
 </dependency>  

Executing the basic HTTP request


The HTTP request is executed with the class Request. The Request has a bunch of methods for building and execution of any HTTP request type.

There is a relevant static method Get, Post, Put etc. for each HTTP request type. Such static method returns the Request instance, which methods are called in chain. Let's see some examples.

Example 1: Get request, which returns content as a string:
 String basicGetRequest() throws ClientProtocolException, IOException {  
      return Request.Get("http://someurl")
                    .execute()
                    .returnContent()
                    .asString();  
 }  
Example 2: Post request with a JSON body and a header, which returns HttpResponse:
 HttpResponse postRequestWithBody(String json) throws ClientProtocolException, IOException {  
      return Request.Post("http://someurl")  
                     .addHeader("app-header", "example")  
                     .bodyString(json, ContentType.APPLICATION_JSON)  
                     .execute()
                     .returnResponse();  
 }  
Fluent request may be executed with the Executor and instead of call of the Request.execute the request is send to the Executor.execute. The above examples may be modified.

Example 3: Get request, which returns content as a string:
 String basicExecutorGetRequest() throws ClientProtocolException, IOException {  
      Executor executor = Executor.newInstance();  
      return executor.execute(Request.Get("http://someurl"))  
                .returnContent().asString();  
 } 
Example 4: Post request with a JSON body and a header, which returns HttpResponse:
 HttpResponse postExecutorRequestWithBody(String json) throws ClientProtocolException, IOException {  
      Executor executor = Executor.newInstance();  
      return executor.execute(Request.Post("http://someurl")  
                .addHeader("app-header", "example")  
                .bodyString(json, ContentType.APPLICATION_JSON))  
                .returnResponse();  
 }  
The Executor style exists for reason. It helps in cases demanding more control on security or other settings, which cannot be specified with the Request. We will consider such example later on in this post.

Adding ResponseHandler


Fluent API implements buffering of the response message in memory. That is why it is strongly recommended to execute fluent HTTP requests with providing the ResponseHandler. The ResponseHandler interface represents a handler, which processes a raw HttpResponse and converts it to an application response object.

Let's see an example.
1. The class AppResponse encapsulates an application response:
 class AppResponse {  
     int httpStatus = HttpStatus.SC_OK;
     String jsonBody = Strings.EMPTY;

     AppResponse(int httpStatus, String jsonBody) {
         this.httpStatus = httpStatus;
         this.jsonBody = jsonBody;
     }
 }  
2. The class AppResponseHandler implements HttpResponse handling and converts it into AppResponse:
 class AppResponseHandler implements ResponseHandler<AppResponse> {  
      @Override  
      public AppResponse handleResponse(HttpResponse response) throws ClientProtocolException, IOException {  
           HttpEntity entity = response.getEntity();  
           ContentResponseHandler contentHandler = new ContentResponseHandler();  
           AppResponse appResponse = new AppResponse(
               response.getStatusLine().getStatusCode(),
               contentHandler.handleEntity(entity).asString());
           return appResponse;
      }  
 }  
3. The HTTP request execution is as following:
 AppResponse appResponse = Request.Get("http://someurl")  
        .execute().handleResponse(new AppResponseHandler());  
 }  

How to ignore SSL certificate errors


The Executor style allows execute HTTP request, which ignores SSL certificate errors. An executor should be created with an untrusted HttpClient like following:
 String ignoreSslErrorsRequest() throws Exception {  
      Executor executor = Executor.newInstance(noSslHttpClient());  
      return executor.execute(Request.Get("http://someurl")).returnContent().asString();  
 }

 private static CloseableHttpClient noSslHttpClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {  
      final SSLContext sslContext = new SSLContextBuilder()  
                .loadTrustMaterial(null, (x509CertChain, authType) -> true)  
                .build();  
      return HttpClientBuilder.create()  
                .setSSLContext(sslContext)  
                .setConnectionManager(  
                          new PoolingHttpClientConnectionManager(  
                                    RegistryBuilder.<ConnectionSocketFactory>create()  
                                    .register("http", PlainConnectionSocketFactory.INSTANCE)  
                                    .register("https", new SSLConnectionSocketFactory(sslContext,  
                                              NoopHostnameVerifier.INSTANCE))  
                                    .build()  
                                    ))  
                .build();  
 }  

How to execute HTTP requests via Proxy


If requests should be done via proxy, the method viaProxy should be called in the Request chain before call to execute. For example:
 HttpResponse requestViaProxy() throws ClientProtocolException, IOException {  
      return Request.Get("http://someurl")  
                .addHeader("app-header", "example")  
                .viaProxy(new HttpHost("myproxy", 8080))  
                .execute().returnResponse();  
 }  
With the Executor it is like this:
 HttpResponse requestViaProxy2() throws ClientProtocolException, IOException {  
      Executor executor = Executor.newInstance();  
      return executor.execute(  
                Request.Get("http://someurl")  
                     .addHeader("app-header", "example")  
                     .viaProxy(new HttpHost("myproxy", 8080)))  
                .returnResponse();  
 }  
Examples on Git.

Useful links:

No comments :

About the author

My Photo
I trust only simple code and believe that code should be handsome. This is not a matter of technology, but professional approach, consolidated after years of software development. I enjoy to cause things working and feel very happy, when I manage to solve a problem.
Back to Top