summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOfir Sonsino <os0695@intl.att.com>2018-08-23 11:31:48 +0000
committerGerrit Code Review <gerrit@onap.org>2018-08-23 11:31:48 +0000
commit5adc0b0ee92d1e39ddaacd27e67a327dd5988f11 (patch)
treebbb51070fd9996ca9e3e5ef85c029aa2da693782
parenteea1c99fcc1ec5a0587f60fe7ac5ba96e186ca81 (diff)
parent985bc34c7519ae45adf464d68315f06972152d0e (diff)
Merge "Generic REST client for external services"
-rwxr-xr-xvid-app-common/pom.xml45
-rw-r--r--vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java228
-rw-r--r--vid-app-common/src/main/java/org/onap/vid/client/SyncRestClientInterface.java30
-rw-r--r--vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java268
-rw-r--r--vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java139
-rw-r--r--vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientModel.java56
6 files changed, 763 insertions, 3 deletions
diff --git a/vid-app-common/pom.xml b/vid-app-common/pom.xml
index b8fbd853a..9a6210b10 100755
--- a/vid-app-common/pom.xml
+++ b/vid-app-common/pom.xml
@@ -250,17 +250,50 @@
<artifactId>opencsv</artifactId>
<version>4.1</version>
</dependency>
-
+
<!-- HTTP client -->
+
+ <dependency>
+ <groupId>io.joshworks.unirest</groupId>
+ <artifactId>unirest-java</artifactId>
+ <version>0.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.3.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpasyncclient</artifactId>
+ <version>4.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpmime</artifactId>
+ <version>4.3.6</version>
+ </dependency>
<dependency>
<groupId>com.xebialabs.restito</groupId>
<artifactId>restito</artifactId>
<version>0.9.3</version>
<scope>test</scope>
</dependency>
-
- <!-- SDK overlay war -->
+ <!-- Helpers -->
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>1.18.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.vavr</groupId>
+ <artifactId>vavr</artifactId>
+ <version>0.9.2</version>
+ </dependency>
+
+ <!-- SDK overlay war -->
<dependency>
<groupId>org.onap.portal.sdk</groupId>
<artifactId>epsdk-app-overlay</artifactId>
@@ -354,6 +387,12 @@
<version>4.12</version>
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ <dependency>
<groupId>com.google.code.bean-matchers</groupId>
<artifactId>bean-matchers</artifactId>
<version>0.11</version>
diff --git a/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java b/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java
new file mode 100644
index 000000000..84e83e8b2
--- /dev/null
+++ b/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClient.java
@@ -0,0 +1,228 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.vid.client;
+
+import io.joshworks.restclient.http.HttpResponse;
+import io.joshworks.restclient.http.JsonNode;
+import io.joshworks.restclient.http.RestClient;
+import io.joshworks.restclient.http.mapper.ObjectMapper;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.eclipse.jetty.util.security.Password;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.conn.ssl.SSLContexts;
+import io.vavr.CheckedFunction1;
+import lombok.SneakyThrows;
+import lombok.val;
+
+import java.security.UnrecoverableKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.KeyManagementException;
+import java.security.cert.CertificateException;
+import javax.net.ssl.SSLHandshakeException;
+import java.security.KeyStoreException;
+import java.text.SimpleDateFormat;
+import javax.net.ssl.SSLContext;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.text.DateFormat;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Map;
+import java.io.File;
+import org.onap.portalsdk.core.util.SystemProperties;
+import org.onap.vid.properties.VidProperties;
+
+public class SyncRestClient implements SyncRestClientInterface {
+
+ private static final String CANNOT_INITIALIZE_CUSTOM_HTTP_CLIENT = "Cannot initialize custom http client from current configuration. Using default one.";
+ private static final String TRY_TO_CALL_OVER_HTTP = "SSL Handshake problem occured. Will try to retry over Http.";
+ private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SyncRestClient.class);
+ private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss:SSSS");
+ private static final String[] SUPPORTED_SSL_VERSIONS = {"TLSv1", "TLSv1.2"};
+ private static final String HTTPS_SCHEMA = "https://";
+ private static final String HTTP_SCHEMA = "http://";
+
+ private RestClient restClient;
+
+ public SyncRestClient() {
+ restClient = RestClient.newClient().objectMapper(defaultObjectMapper()).httpClient(defaultHttpClient()).build();
+ }
+
+ public SyncRestClient(ObjectMapper objectMapper) {
+ restClient = RestClient.newClient().objectMapper(objectMapper).httpClient(defaultHttpClient()).build();
+ }
+
+ public SyncRestClient(CloseableHttpClient httpClient) {
+ restClient = RestClient.newClient().objectMapper(defaultObjectMapper()).httpClient(httpClient).build();
+ }
+
+ public SyncRestClient(CloseableHttpClient httpClient, ObjectMapper objectMapper) {
+ restClient = RestClient.newClient().objectMapper(objectMapper).httpClient(httpClient).build();
+ }
+
+ @Override
+ public HttpResponse<JsonNode> post(String url, Map<String, String> headers, Object body) {
+ return callWithRetryOverHttp(url, url2 -> restClient.post(url2).headers(headers).body(body).asJson());
+ }
+
+ @Override
+ public <T> HttpResponse<T> post(String url, Map<String, String> headers, Object body, Class<T> responseClass) {
+ return callWithRetryOverHttp(url,
+ url2 -> restClient.post(url2).headers(headers).body(body).asObject(responseClass));
+ }
+
+ @Override
+ public HttpResponse<JsonNode> get(String url, Map<String, String> headers, Map<String, String> routeParams) {
+ return callWithRetryOverHttp(url, url2 -> {
+ val getRequest = restClient.get(url2).headers(headers);
+ routeParams.forEach(getRequest::routeParam);
+ return getRequest.asJson();
+ });
+ }
+
+ @Override
+ public <T> HttpResponse<T> get(String url, Map<String, String> headers, Map<String, String> routeParams,
+ Class<T> responseClass) {
+ return callWithRetryOverHttp(url, url2 -> {
+ val getRequest = restClient.get(url2).headers(headers);
+ routeParams.forEach(getRequest::routeParam);
+ return getRequest.asObject(responseClass);
+ });
+ }
+
+ @Override
+ public HttpResponse<InputStream> getStream(String url, Map<String, String> headers,
+ Map<String, String> routeParams) {
+ return callWithRetryOverHttp(url, url2 -> {
+ val getRequest = restClient.get(url2).headers(headers);
+ routeParams.forEach(getRequest::routeParam);
+ return getRequest.asBinary();
+ });
+ }
+
+ @Override
+ public HttpResponse<JsonNode> put(String url, Map<String, String> headers, Object body) {
+ return callWithRetryOverHttp(url, url2 -> restClient.put(url2).headers(headers).body(body).asJson());
+ }
+
+ @Override
+ public <T> HttpResponse<T> put(String url, Map<String, String> headers, Object body, Class<T> responseClass) {
+ return callWithRetryOverHttp(url,
+ url2 -> restClient.put(url2).headers(headers).body(body).asObject(responseClass));
+ }
+
+ @Override
+ public <T> HttpResponse<T> delete(String url, Map<String, String> headers, Class<T> responseClass) {
+ return callWithRetryOverHttp(url, url2 -> restClient.delete(url2).headers(headers).asObject(responseClass));
+ }
+
+ @Override
+ public HttpResponse<JsonNode> delete(String url, Map<String, String> headers) {
+ return callWithRetryOverHttp(url, url2 -> restClient.delete(url2).headers(headers).asJson());
+ }
+
+ @Override
+ public void destroy() {
+ restClient.shutdown();
+ }
+
+ @SneakyThrows
+ private <T> HttpResponse<T> callWithRetryOverHttp(String url,
+ CheckedFunction1<String, HttpResponse<T>> httpRequest) {
+ try {
+ return httpRequest.apply(url);
+ } catch (Exception e) {
+ if (e.getCause() instanceof SSLHandshakeException) {
+ logger.warn(EELFLoggerDelegate.debugLogger,
+ DATE_FORMAT.format(new Date()) + TRY_TO_CALL_OVER_HTTP, e);
+ return httpRequest.apply(url.replaceFirst(HTTPS_SCHEMA, HTTP_SCHEMA));
+ }
+ throw e;
+ }
+ }
+
+ private ObjectMapper defaultObjectMapper() {
+ val objectMapper = new org.codehaus.jackson.map.ObjectMapper();
+
+ return new ObjectMapper() {
+ @Override
+ @SneakyThrows
+ public <T> T readValue(String value, Class<T> aClass) {
+ return objectMapper.readValue(value, aClass);
+ }
+
+ @Override
+ @SneakyThrows
+ public String writeValue(Object value) {
+ return objectMapper.writeValueAsString(value);
+ }
+ };
+ }
+
+ private CloseableHttpClient defaultHttpClient() {
+ try {
+ val trustStorePath = SystemProperties.getProperty(VidProperties.VID_TRUSTSTORE_FILENAME);
+ val trustStorePass = SystemProperties.getProperty(VidProperties.VID_TRUSTSTORE_PASSWD_X);
+ val decryptedTrustStorePass = Password.deobfuscate(trustStorePass);
+
+ val trustStore = loadTruststore(trustStorePath, decryptedTrustStorePass);
+ val sslContext = trustOwnCACerts(decryptedTrustStorePass, trustStore);
+ val sslSf = allowTLSProtocols(sslContext);
+
+ return HttpClients.custom().setSSLSocketFactory(sslSf).build();
+ } catch (IOException | CertificateException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
+ logger.warn(EELFLoggerDelegate.debugLogger,
+ DATE_FORMAT.format(new Date()) + CANNOT_INITIALIZE_CUSTOM_HTTP_CLIENT, e);
+ return HttpClients.createDefault();
+ }
+ }
+
+ private SSLConnectionSocketFactory allowTLSProtocols(SSLContext sslcontext) {
+ return new SSLConnectionSocketFactory(
+ sslcontext,
+ SUPPORTED_SSL_VERSIONS,
+ null,
+ SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ }
+
+ private SSLContext trustOwnCACerts(String trustStorePass, KeyStore trustStore)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ return SSLContexts.custom()
+ .useTLS()
+ .loadKeyMaterial(trustStore, trustStorePass.toCharArray())
+ .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
+ .build();
+ }
+
+ private KeyStore loadTruststore(String trustStorePath, String trustStorePass)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+ val trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ try (FileInputStream instream = new FileInputStream(new File(trustStorePath))) {
+ trustStore.load(instream, trustStorePass.toCharArray());
+ }
+ return trustStore;
+ }
+
+}
diff --git a/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClientInterface.java b/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClientInterface.java
new file mode 100644
index 000000000..80663d65b
--- /dev/null
+++ b/vid-app-common/src/main/java/org/onap/vid/client/SyncRestClientInterface.java
@@ -0,0 +1,30 @@
+package org.onap.vid.client;
+
+import io.joshworks.restclient.http.HttpResponse;
+import io.joshworks.restclient.http.JsonNode;
+import java.io.InputStream;
+import java.util.Map;
+
+public interface SyncRestClientInterface {
+
+ HttpResponse<JsonNode> post(String url, Map<String, String> headers, Object body);
+
+ <T> HttpResponse<T> post(String url, Map<String, String> headers, Object body, Class<T> aClass);
+
+ HttpResponse<JsonNode> get(String url, Map<String, String> headers, Map<String, String> routeParams);
+
+ <T> HttpResponse<T> get(String url, Map<String, String> headers, Map<String, String> routeParams, Class<T> aClass);
+
+ HttpResponse<InputStream> getStream(String url, Map<String, String> headers, Map<String, String> routeParams);
+
+ HttpResponse<JsonNode> put(String url, Map<String, String> headers, Object body);
+
+ <T> HttpResponse<T> put(String url, Map<String, String> headers, Object body, Class<T> aClass);
+
+ <T> HttpResponse<T> delete(String url, Map<String, String> headers, Class<T> aClass);
+
+ HttpResponse<JsonNode> delete(String url, Map<String, String> headers);
+
+ void destroy();
+
+}
diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java
new file mode 100644
index 000000000..d63d144e6
--- /dev/null
+++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java
@@ -0,0 +1,268 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.vid.client;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableMap;
+import com.xebialabs.restito.semantics.Condition;
+import com.xebialabs.restito.server.StubServer;
+import io.joshworks.restclient.http.HttpResponse;
+import io.joshworks.restclient.http.JsonNode;
+import org.glassfish.grizzly.http.util.HttpStatus;
+import com.xebialabs.restito.semantics.Action;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.AfterMethod;
+import org.glassfish.grizzly.http.Method;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static com.xebialabs.restito.builder.verify.VerifyHttp.verifyHttp;
+import static com.xebialabs.restito.builder.stub.StubHttp.whenHttp;
+import static com.xebialabs.restito.semantics.Action.stringContent;
+import static com.xebialabs.restito.semantics.Action.contentType;
+import static com.xebialabs.restito.semantics.Action.status;
+import static com.xebialabs.restito.semantics.Action.ok;
+import static org.testng.Assert.assertEquals;
+
+public class SyncRestClientForHttpServerTest {
+
+ private static final SyncRestClientModel.TestModel testObject = new SyncRestClientModel.TestModel(1, "test");
+ private static final String NOT_EXISTING_OBJECT = "NOT EXISTING OBJECT";
+
+ private StubServer stubServer;
+ private ObjectMapper objectMapper = new ObjectMapper();
+ private SyncRestClient syncRestClient;
+
+ @BeforeMethod
+ public void setUp() {
+ stubServer = new StubServer();
+ stubServer.run();
+ syncRestClient = new SyncRestClient();
+ }
+
+ @AfterMethod
+ public void tearDown() {
+ stubServer.stop();
+ syncRestClient.destroy();
+ }
+
+ @Test
+ public void testJsonResponseFromGet() throws JsonProcessingException {
+ // given
+ stubGetCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient
+ .get(url, Collections.emptyMap(), Collections.emptyMap());
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.GET), Condition.url(url));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 200);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("key"), 1);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("value"), "test");
+ }
+
+ @Test
+ public void testObjectResponseFromGet() throws JsonProcessingException {
+ // given
+ stubGetCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<SyncRestClientModel.TestModel> testModelHttpResponse = syncRestClient
+ .get(url, Collections.emptyMap(), Collections.emptyMap(), SyncRestClientModel.TestModel.class);
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.GET), Condition.url(url));
+ assertEquals(testModelHttpResponse.getStatus(), 200);
+ assertEquals(testModelHttpResponse.getBody().getKey(), 1);
+ assertEquals(testModelHttpResponse.getBody().getValue(), "test");
+ }
+
+ @Test
+ public void testJsonResponseFromPost() throws JsonProcessingException {
+ // given
+ stubPostCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.post(url, Collections.emptyMap(), testObject);
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.POST), Condition.url(url));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 200);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("key"), 1);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("value"), "test");
+ }
+
+ @Test
+ public void test404JsonResponseFromPost() throws JsonProcessingException {
+ // given
+ stubPostCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient
+ .post(url, Collections.emptyMap(), NOT_EXISTING_OBJECT);
+ // then
+ assertEquals(jsonNodeHttpResponse.getStatus(), 404);
+ assertEquals(jsonNodeHttpResponse.getStatusText(), "Not Found");
+ }
+
+ @Test
+ public void testHeadersWerePassedToPost() throws JsonProcessingException {
+ // given
+ stubPostCall();
+ Map headers = ImmutableMap.<String, String>builder().put("Authorization", "Basic anyHash").build();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.post(url, headers, testObject);
+ // then
+ verifyHttp(stubServer).once(Condition.withHeader("Authorization"));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 200);
+ }
+
+ @Test(expectedExceptions = {Exception.class})
+ public void testFailedJsonResponseFromPost() throws JsonProcessingException {
+ // given
+ stubPostCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ stubServer.stop();
+ syncRestClient.post(url, Collections.emptyMap(), testObject);
+ }
+
+ @Test
+ public void testObjectResponseFromPost() throws JsonProcessingException {
+ // given
+ stubPostCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<SyncRestClientModel.TestModel> objectHttpResponse = syncRestClient
+ .post(url, Collections.emptyMap(), testObject, SyncRestClientModel.TestModel.class);
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.POST), Condition.url(url));
+ assertEquals(objectHttpResponse.getStatus(), 200);
+ assertEquals(objectHttpResponse.getBody().getKey(), 1);
+ assertEquals(objectHttpResponse.getBody().getValue(), "test");
+ }
+
+ @Test
+ public void testJsonResponseFromPut() throws JsonProcessingException {
+ // given
+ stubPutCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.put(url, Collections.emptyMap(), testObject);
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.PUT), Condition.url(url));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 201);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("key"), 1);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("value"), "test");
+ }
+
+ @Test
+ public void testObjectResponseFromPut() throws JsonProcessingException {
+ // given
+ stubPutCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<SyncRestClientModel.TestModel> modelHttpResponse = syncRestClient
+ .put(url, Collections.emptyMap(), testObject, SyncRestClientModel.TestModel.class);
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.PUT), Condition.url(url));
+ assertEquals(modelHttpResponse.getStatus(), 201);
+ assertEquals(modelHttpResponse.getBody().getKey(), 1);
+ assertEquals(modelHttpResponse.getBody().getValue(), "test");
+ }
+
+ @Test
+ public void testJsonResponseFromDelete() throws JsonProcessingException {
+ // given
+ stubDeleteCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.delete(url, Collections.emptyMap());
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.DELETE), Condition.url(url));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 200);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("key"), 1);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("value"), "test");
+ }
+
+ @Test
+ public void testObjectResponseFromDelete() throws JsonProcessingException {
+ // given
+ stubDeleteCall();
+ String url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<SyncRestClientModel.TestModel> modelHttpResponse = syncRestClient
+ .delete(url, Collections.emptyMap(), SyncRestClientModel.TestModel.class);
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.DELETE), Condition.url(url));
+ assertEquals(modelHttpResponse.getStatus(), 200);
+ assertEquals(modelHttpResponse.getBody().getKey(), 1);
+ assertEquals(modelHttpResponse.getBody().getValue(), "test");
+ }
+
+ @Test
+ public void testRedirectToHttp() throws JsonProcessingException {
+ // given
+ stubGetCall();
+ String secured_url = "https://0.0.0.0:" + stubServer.getPort() + "/test";
+ String available_url = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient
+ .get(secured_url, Collections.emptyMap(), Collections.emptyMap());
+ // then
+ verifyHttp(stubServer).once(Condition.method(Method.GET), Condition.url(available_url),
+ Condition.not(Condition.url(secured_url)));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 200);
+ }
+
+ private void stubGetCall() throws JsonProcessingException {
+ whenHttp(stubServer)
+ .match(Condition.get("/test"))
+ .then(ok(), jsonContent(), contentType("application/json"));
+ }
+
+ private void stubDeleteCall() throws JsonProcessingException {
+ whenHttp(stubServer)
+ .match(Condition.delete("/test"))
+ .then(ok(), jsonContent(), contentType("application/json"));
+ }
+
+ private void stubPostCall() throws JsonProcessingException {
+ whenHttp(stubServer)
+ .match(Condition.post("/test"),
+ Condition.withPostBodyContaining(objectMapper.writeValueAsString(testObject)))
+ .then(ok(), jsonContent(), contentType("application/json"));
+ }
+
+ private void stubPutCall() throws JsonProcessingException {
+ whenHttp(stubServer)
+ .match(Condition.put("/test"),
+ Condition.withPostBodyContaining(objectMapper.writeValueAsString(testObject)))
+ .then(status(HttpStatus.CREATED_201), jsonContent(), contentType("application/json"));
+ }
+
+ private Action jsonContent() throws JsonProcessingException {
+ return stringContent(objectMapper.writeValueAsString(testObject));
+ }
+
+} \ No newline at end of file
diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java
new file mode 100644
index 000000000..ba6da4351
--- /dev/null
+++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java
@@ -0,0 +1,139 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.vid.client;
+
+import io.joshworks.restclient.http.HttpResponse;
+import io.joshworks.restclient.http.JsonNode;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.conn.ssl.SSLContextBuilder;
+import com.xebialabs.restito.semantics.Condition;
+import com.xebialabs.restito.server.StubServer;
+import com.xebialabs.restito.semantics.Action;
+import org.apache.http.config.RegistryBuilder;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.AfterMethod;
+import org.glassfish.grizzly.http.Method;
+import org.apache.http.client.HttpClient;
+import org.apache.http.config.Registry;
+import org.testng.annotations.Test;
+
+import java.security.GeneralSecurityException;
+import javax.net.ssl.SSLContext;
+import java.util.Collections;
+
+import static com.xebialabs.restito.builder.verify.VerifyHttp.verifyHttp;
+import static com.xebialabs.restito.builder.stub.StubHttp.whenHttp;
+import static com.xebialabs.restito.semantics.Action.stringContent;
+import static com.xebialabs.restito.semantics.Action.contentType;
+import static org.apache.http.client.config.RequestConfig.custom;
+import static com.xebialabs.restito.semantics.Action.ok;
+import static org.testng.Assert.assertEquals;
+
+public class SyncRestClientForHttpsServerTest {
+
+ private static final SyncRestClientModel.TestModel testObject = new SyncRestClientModel.TestModel(1, "test");
+ private static final String[] SUPPORTED_PROTOCOLS = {"TLSv1", "TLSv1.2"};
+ private StubServer stubServer;
+ private ObjectMapper objectMapper = new ObjectMapper();
+
+ private SyncRestClient syncRestClient;
+
+ @BeforeMethod
+ public void setUp() throws GeneralSecurityException {
+ stubServer = new StubServer();
+ stubServer.secured().run();
+ syncRestClient = new SyncRestClient(createNaiveHttpClient());
+ }
+
+ @AfterMethod
+ public void tearDown() {
+ stubServer.stop();
+ }
+
+ @Test
+ public void testJsonResponseFromGet() throws JsonProcessingException {
+ // given
+ stubGetCall();
+ String securedUrl = "https://0.0.0.0:" + stubServer.getPort() + "/test";
+ String notSecuredUrl = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient
+ .get(securedUrl, Collections.emptyMap(), Collections.emptyMap());
+ // then
+ verifyHttp(stubServer)
+ .once(Condition.method(Method.GET), Condition.url(securedUrl), Condition.not(Condition.url(notSecuredUrl)));
+ assertEquals(jsonNodeHttpResponse.getStatus(), 200);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("key"), 1);
+ assertEquals(jsonNodeHttpResponse.getBody().getObject().get("value"), "test");
+ }
+
+ @Test
+ public void testObjectResponseFromGet() throws JsonProcessingException {
+ // given
+ stubServer.run();
+ stubGetCall();
+ String securedUrl = "https://0.0.0.0:" + stubServer.getPort() + "/test";
+ String notSecuredUrl = "http://0.0.0.0:" + stubServer.getPort() + "/test";
+ // when
+ HttpResponse<SyncRestClientModel.TestModel> testModelHttpResponse = syncRestClient
+ .get(securedUrl, Collections.emptyMap(), Collections.emptyMap(), SyncRestClientModel.TestModel.class);
+ // then
+ verifyHttp(stubServer)
+ .once(Condition.method(Method.GET), Condition.url(securedUrl), Condition.not(Condition.url(notSecuredUrl)));
+ assertEquals(testModelHttpResponse.getStatus(), 200);
+ assertEquals(testModelHttpResponse.getBody().getKey(), 1);
+ assertEquals(testModelHttpResponse.getBody().getValue(), "test");
+ }
+
+ private Action jsonContent() throws JsonProcessingException {
+ return stringContent(objectMapper.writeValueAsString(testObject));
+ }
+
+ private void stubGetCall() throws JsonProcessingException {
+ whenHttp(stubServer)
+ .match(Condition.get("/test"))
+ .then(ok(), jsonContent(), contentType("application/json"));
+ }
+
+ private CloseableHttpClient createNaiveHttpClient() throws GeneralSecurityException {
+ final SSLContext context = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
+ .build();
+
+ final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(context, SUPPORTED_PROTOCOLS,
+ null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("https", socketFactory)
+ .build();
+
+ return HttpClientBuilder.create()
+ .setDefaultRequestConfig(custom().setConnectionRequestTimeout(10000).build())
+ .setConnectionManager(new PoolingHttpClientConnectionManager(registry))
+ .setSSLSocketFactory(socketFactory).build();
+ }
+
+} \ No newline at end of file
diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientModel.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientModel.java
new file mode 100644
index 000000000..b64988a23
--- /dev/null
+++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientModel.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.vid.client;
+
+class SyncRestClientModel {
+
+ static class TestModel{
+
+ public TestModel() {
+ // needed by the object mappers
+ }
+
+ public TestModel(long key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ private long key;
+ private String value;
+
+ public void setKey(long key) {
+ this.key = key;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public long getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+}