Repository: authorjapps/zerocode
Pull request #15 (2018-01-25 17:33:15)

ISSUE-14 # Fixed. SSL Auto trusted for CustoHttpClient
Dear Author, 
please review, approve n merge if possible. 
Regards, 
Sameer


Patch:
diff --git a/pom.xml b/pom.xml
index d1ace006..0dbe296f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,6 +68,7 @@
         <jackson-dataformat-csv.version>2.7.0</jackson-dataformat-csv.version>
         <commons-io.version>2.4</commons-io.version>
         <micro-simulator.version>1.1.10</micro-simulator.version>
+        <httpclient.version>4.5</httpclient.version>
 
         <!-- maven plugin build related  -->
         <maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
@@ -179,12 +180,18 @@
             <version>${junit.version}</version>
             <!--<scope>test</scope>--> <!-- added with compile scope. Do not change this -->
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.jsmart</groupId>
             <artifactId>micro-simulator</artifactId>
             <version>${micro-simulator.version}</version>
             <scope>test</scope>
         </dependency>
+
     </dependencies>
 
     <profiles>
diff --git a/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java b/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java
new file mode 100644
index 00000000..88fc5af2
--- /dev/null
+++ b/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java
@@ -0,0 +1,156 @@
+package org.jsmart.zerocode.core.httpclient.ssl;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.CookieStore;
+import org.apache.http.client.entity.EntityBuilder;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLContextBuilder;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.jsmart.zerocode.core.httpclient.BasicHttpClient;
+import org.jsmart.zerocode.core.httpclient.RestEasyDefaultHttpClient;
+import org.jsmart.zerocode.core.utils.HelperJsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.core.Response;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+import static java.lang.String.format;
+import static org.apache.http.entity.ContentType.APPLICATION_JSON;
+import static org.jsmart.zerocode.core.utils.HelperJsonUtils.getContentAsItIsJson;
+
+public class SslTrustHttpClient implements BasicHttpClient {
+    private static final Logger LOGGER = LoggerFactory.getLogger(RestEasyDefaultHttpClient.class);
+
+    private Object COOKIE_JSESSIONID_VALUE;
+
+    @Override
+    public Response execute(String httpUrl, String methodName, Map<String, Object> headers, Map<String, Object> queryParams, Object body) throws Exception {
+
+        LOGGER.info("###Used SSL Enabled Http Client");
+
+        /** ---------------------------
+         * Get the request body content
+         * ----------------------------
+         */
+        String reqBodyAsString = getContentAsItIsJson(body);
+
+        CloseableHttpClient httpclient = createSslHttpClient();
+
+        /** -----------------------
+         * set the query parameters
+         * ------------------------
+         */
+        if (queryParams != null) {
+            httpUrl = setQueryParams(httpUrl, queryParams);
+        }
+
+        RequestBuilder requestBuilder = RequestBuilder
+                .create(methodName)
+                .setUri(httpUrl);
+
+        if (reqBodyAsString != null) {
+            HttpEntity httpEntity = EntityBuilder.create()
+                    .setContentType(APPLICATION_JSON)
+                    .setText(reqBodyAsString)
+                    .build();
+            requestBuilder.setEntity(httpEntity);
+        }
+
+        /** --------------
+         * set the headers
+         * ---------------
+         */
+        if (headers != null) {
+            Map headersMap = headers;
+            for (Object key : headersMap.keySet()) {
+                requestBuilder.addHeader((String) key, (String) headersMap.get(key));
+            }
+        }
+
+        /** -----------------------------------------------------------------------------------
+         * Setting cookies:
+         *
+         * Highly discouraged to use sessions, but in case of any server dependent upon session,
+         * then it's taken care here.
+         * ------------------------------------------------------------------------------------
+         */
+        if (COOKIE_JSESSIONID_VALUE != null) {
+            requestBuilder.addHeader("Cookie", (String) COOKIE_JSESSIONID_VALUE);
+        }
+
+        /** ----------------------
+         * now execute the request
+         * -----------------------
+         */
+        CloseableHttpResponse httpResponse = httpclient.execute(requestBuilder.build());
+
+        Response serverResponse = Response
+                .status(httpResponse.getStatusLine().getStatusCode())
+                .entity(IOUtils.toString(httpResponse.getEntity().getContent(), "UTF-8"))
+                .build();
+
+
+        Header[] allHeaders = httpResponse.getAllHeaders();
+        Response.ResponseBuilder responseBuilder = Response.fromResponse(serverResponse);
+        for (Header thisHeader : allHeaders) {
+            String headerKey = thisHeader.getName();
+            responseBuilder = responseBuilder.header(headerKey, thisHeader.getValue());
+
+            /** ---------------
+             * Session handled
+             * ----------------
+             */
+            if ("Set-Cookie".equals(headerKey)) {
+                COOKIE_JSESSIONID_VALUE = serverResponse.getMetadata().get(headerKey);
+            }
+        }
+        serverResponse = responseBuilder.build();
+
+        return serverResponse;
+    }
+
+    private CloseableHttpClient createSslHttpClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
+        SSLContext sslContext = new SSLContextBuilder()
+                .loadTrustMaterial(null, (certificate, authType) -> true).build();
+
+        CookieStore cookieStore = new BasicCookieStore();
+
+        return HttpClients.custom()
+                .setSSLContext(sslContext)
+                .setSSLHostnameVerifier(new NoopHostnameVerifier())
+                .setDefaultCookieStore(cookieStore)
+                .build();
+    }
+
+    private String setQueryParams(String httpUrl, Map<String, Object> queryParams) {
+        String qualifiedQueryParams = createQualifiedQueryParams(queryParams);
+        httpUrl = httpUrl + qualifiedQueryParams;
+        return httpUrl;
+    }
+
+    private String createQualifiedQueryParams(Object queryParams) {
+        String qualifiedQueryParam = "?";
+        Map queryParamsMap = HelperJsonUtils.readHeadersAsMap(queryParams);
+        for (Object key : queryParamsMap.keySet()) {
+            if ("?".equals(qualifiedQueryParam)) {
+                qualifiedQueryParam = qualifiedQueryParam + format("%s=%s", key, queryParamsMap.get(key));
+            } else {
+                qualifiedQueryParam = qualifiedQueryParam + format("&%s=%s", key, queryParamsMap.get(key));
+            }
+        }
+        return qualifiedQueryParam;
+    }
+
+}
+


Test patch:
diff --git a/src/main/resources/01_verification_test_cases/21_ssl_trust.json b/src/main/resources/01_verification_test_cases/21_ssl_trust.json
new file mode 100644
index 00000000..1547b39c
--- /dev/null
+++ b/src/main/resources/01_verification_test_cases/21_ssl_trust.json
@@ -0,0 +1,30 @@
+{
+    "scenarioName": "21_ssl_trust_scenario",
+    "steps": [
+        {
+            "name": "ssl_trust_step",
+            "url": "http://localhost:9998/home/bathroom/1",
+            "operation": "GET",
+            "request": {
+                "headers": {
+                    "Content-Type": "application/json;charset=UTF-8",
+                    "Cookie": "cookie_123"
+                },
+                "body": {
+                }
+            },
+            "assertions": {
+                "status": 200,
+                "headers": {
+                    "Content-Type": ["application/json"],
+                    "Connection": ["keep-alive"]
+                },
+                "body" : {
+                    "id" : 1,
+                    "name" : "Shower",
+                    "availability" : true
+                }
+            }
+        }
+    ]
+}
diff --git a/src/test/java/org/jsmart/zerocode/core/verification/SslTrustUseHttpClientTest.java b/src/test/java/org/jsmart/zerocode/core/verification/SslTrustUseHttpClientTest.java
new file mode 100644
index 00000000..f0c456ee
--- /dev/null
+++ b/src/test/java/org/jsmart/zerocode/core/verification/SslTrustUseHttpClientTest.java
@@ -0,0 +1,22 @@
+package org.jsmart.zerocode.core.verification;
+
+import org.jsmart.zerocode.core.domain.JsonTestCase;
+import org.jsmart.zerocode.core.domain.TargetEnv;
+import org.jsmart.zerocode.core.domain.UseHttpClient;
+import org.jsmart.zerocode.core.httpclient.ssl.SslTrustHttpClient;
+import org.jsmart.zerocode.core.tests.customrunner.TestOnlyZeroCodeUnitRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@UseHttpClient(SslTrustHttpClient.class)
+@TargetEnv("config_hosts.properties")
+@RunWith(TestOnlyZeroCodeUnitRunner.class)
+public class SslTrustUseHttpClientTest {
+
+    @Test
+    @JsonTestCase("01_verification_test_cases/21_ssl_trust.json")
+    public void testASmartTestCase_createUpdate() throws Exception {
+
+    }
+}
+
diff --git a/src/test/java/org/jsmart/zerocode/core/verification/ZeroCodeUnitCustomRuntimeUseHttpClientTest.java b/src/test/java/org/jsmart/zerocode/core/verification/ZeroCodeUnitCustomRuntimeUseHttpClientTest.java
index 6097fa7b..e91c37d5 100644
--- a/src/test/java/org/jsmart/zerocode/core/verification/ZeroCodeUnitCustomRuntimeUseHttpClientTest.java
+++ b/src/test/java/org/jsmart/zerocode/core/verification/ZeroCodeUnitCustomRuntimeUseHttpClientTest.java
@@ -8,7 +8,7 @@ import org.jsmart.zerocode.core.tests.customrunner.TestOnlyZeroCodeUnitRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-@UseHttpClient(CustomRuntimeTestHttpClient.class)
+@UseHttpClient(CustomRuntimeTestHttpClient.class) //<--- This sets some header also eg "key1"
 @TargetEnv("config_hosts.properties")
 @RunWith(TestOnlyZeroCodeUnitRunner.class)
 public class ZeroCodeUnitCustomRuntimeUseHttpClientTest {