diff options
author | Oleg Mitsura <oleg.mitsura@amdocs.com> | 2019-05-13 15:49:03 -0400 |
---|---|---|
committer | Oleg Mitsura <oleg.mitsura@amdocs.com> | 2019-05-15 16:26:34 -0400 |
commit | 9eb8b8a88bfac860a94b62b203b00c64330a1be7 (patch) | |
tree | 1e7403f7a53599f7708d172ae61b3dbc0e1b55ac /ms/blueprintsprocessor/modules/commons | |
parent | 250b5b2a4ad4020df9c0dd053743d28616e28485 (diff) |
BlueprintWebClientService: added return status
Issue-ID: CCSDK-1331
Change-Id: I8dab8ad4eaebf1863f11c4d38c52cf7f64b0a4d5
Signed-off-by: Oleg Mitsura <oleg.mitsura@amdocs.com>
Diffstat (limited to 'ms/blueprintsprocessor/modules/commons')
2 files changed, 119 insertions, 137 deletions
diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt index d6d02b330..5d35186b8 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt @@ -22,11 +22,13 @@ import com.fasterxml.jackson.databind.JsonNode import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.apache.commons.io.IOUtils +import org.apache.http.client.ClientProtocolException import org.apache.http.client.methods.HttpDelete import org.apache.http.client.methods.HttpGet import org.apache.http.client.methods.HttpPatch import org.apache.http.client.methods.HttpPost import org.apache.http.client.methods.HttpPut +import org.apache.http.client.methods.HttpUriRequest import org.apache.http.entity.StringEntity import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClients @@ -35,6 +37,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.http.HttpMethod +import java.io.IOException import java.io.InputStream import java.nio.charset.Charset @@ -46,206 +49,183 @@ interface BlueprintWebClientService { fun httpClient(): CloseableHttpClient { return HttpClients.custom() - .addInterceptorFirst(WebClientUtils.logRequest()) - .addInterceptorLast(WebClientUtils.logResponse()) - .build() + .addInterceptorFirst(WebClientUtils.logRequest()) + .addInterceptorLast(WebClientUtils.logResponse()) + .build() } - fun exchangeResource(methodType: String, path: String, request: String): - String { - return this.exchangeResource(methodType, path, request, - defaultHeaders()) + fun exchangeResource(methodType: String, path: String, request: String): WebClientResponse<String> { + return this.exchangeResource(methodType, path, request, defaultHeaders()) } fun exchangeResource(methodType: String, path: String, request: String, - headers: Map<String, String>): String { - val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders( - headers) + headers: Map<String, String>): WebClientResponse<String> { + /** + * TODO: Basic headers in the implementations of this client do not get added + * in blocking version, whereas in NB version defaultHeaders get added. + * the difference is in convertToBasicHeaders vs basicHeaders + */ + val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders(headers) return when (HttpMethod.resolve(methodType)) { - HttpMethod.DELETE -> delete(path, convertedHeaders) - HttpMethod.GET -> get(path, convertedHeaders) - HttpMethod.POST -> post(path, request, convertedHeaders) - HttpMethod.PUT -> put(path, request, convertedHeaders) - HttpMethod.PATCH -> patch(path, request, convertedHeaders) + HttpMethod.DELETE -> delete(path, convertedHeaders, String::class.java) + HttpMethod.GET -> get(path, convertedHeaders, String::class.java) + HttpMethod.POST -> post(path, request, convertedHeaders, String::class.java) + HttpMethod.PUT -> put(path, request, convertedHeaders, String::class.java) + HttpMethod.PATCH -> patch(path, request, convertedHeaders, String::class.java) else -> throw BluePrintProcessorException("Unsupported met" + - "hodType($methodType)") + "hodType($methodType)") } } fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> { - return headers.map{ BasicHeader(it.key, it.value)}.toTypedArray() + return headers.map { BasicHeader(it.key, it.value) }.toTypedArray() } - fun delete(path: String, headers: Array<BasicHeader>): String { + fun <T> delete(path: String, headers: Array<BasicHeader>, responseType: Class<T>): WebClientResponse<T> { val httpDelete = HttpDelete(host(path)) httpDelete.setHeaders(headers) - httpClient().execute(httpDelete).entity.content.use { - return IOUtils.toString(it, Charset.defaultCharset()) - } + return performCallAndExtractTypedWebClientResponse(httpDelete, responseType) } - fun get(path: String, headers: Array<BasicHeader>): String { + fun <T> get(path: String, headers: Array<BasicHeader>, responseType: Class<T>): WebClientResponse<T> { val httpGet = HttpGet(host(path)) httpGet.setHeaders(headers) - httpClient().execute(httpGet).entity.content.use { - return IOUtils.toString(it, Charset.defaultCharset()) - } + return performCallAndExtractTypedWebClientResponse(httpGet, responseType) } - fun post(path: String, request: String, headers: Array<BasicHeader>): - String { + fun <T> post(path: String, request: Any, headers: Array<BasicHeader>, responseType: Class<T>): WebClientResponse<T> { val httpPost = HttpPost(host(path)) - val entity = StringEntity(request) + val entity = StringEntity(strRequest(request)) httpPost.entity = entity httpPost.setHeaders(headers) - httpClient().execute(httpPost).entity.content.use { - return IOUtils.toString(it, Charset.defaultCharset()) - } + return performCallAndExtractTypedWebClientResponse(httpPost, responseType) } - fun put(path: String, request: String, headers: Array<BasicHeader>): - String { + fun <T> put(path: String, request: Any, headers: Array<BasicHeader>, responseType: Class<T>): WebClientResponse<T> { val httpPut = HttpPut(host(path)) - val entity = StringEntity(request) + val entity = StringEntity(strRequest(request)) httpPut.entity = entity httpPut.setHeaders(headers) - httpClient().execute(httpPut).entity.content.use { - return IOUtils.toString(it, Charset.defaultCharset()) - } + return performCallAndExtractTypedWebClientResponse(httpPut, responseType) } - fun patch(path: String, request: String, headers: Array<BasicHeader>): - String { + fun <T> patch(path: String, request: Any, headers: Array<BasicHeader>, responseType: Class<T>): WebClientResponse<T> { val httpPatch = HttpPatch(host(path)) - val entity = StringEntity(request) + val entity = StringEntity(strRequest(request)) httpPatch.entity = entity httpPatch.setHeaders(headers) - httpClient().execute(httpPatch).entity.content.use { - return IOUtils.toString(it, Charset.defaultCharset()) - } + return performCallAndExtractTypedWebClientResponse(httpPatch, responseType) } + /** + * Perform the HTTP call and return HTTP status code and body. + * @param httpUriRequest {@link HttpUriRequest} object + * @return {@link WebClientResponse} object + * http client may throw IOException and ClientProtocolException on error + */ + + @Throws(IOException::class, ClientProtocolException::class) + private fun <T> performCallAndExtractTypedWebClientResponse( + httpUriRequest: HttpUriRequest, responseType: Class<T>): + WebClientResponse<T> { + val httpResponse = httpClient().execute(httpUriRequest) + val statusCode = httpResponse.statusLine.statusCode + httpResponse.entity.content.use { + val body = getResponse(it, responseType) + return WebClientResponse(statusCode, body) + } + } - suspend fun getNB(path: String): String { + suspend fun getNB(path: String): WebClientResponse<String> { return getNB(path, null, String::class.java) } - suspend fun getNB(path: String, additionalHeaders: Map<String, String>?): - String { + suspend fun getNB(path: String, additionalHeaders: Array<BasicHeader>?): WebClientResponse<String> { return getNB(path, additionalHeaders, String::class.java) } - suspend fun <T> getNB(path: String, additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = - withContext(Dispatchers.IO) { - val httpGet = HttpGet(host(path)) - httpGet.setHeaders(basicHeaders(additionalHeaders)) - httpClientNB().execute(httpGet).entity.content.use { - getResponse(it, responseType) + suspend fun <T> getNB(path: String, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>): + WebClientResponse<T> = + withContext(Dispatchers.IO) { + get(path, additionalHeaders!!, responseType) } - } - suspend fun postNB(path: String, request: Any): String { + suspend fun postNB(path: String, request: Any): WebClientResponse<String> { return postNB(path, request, null, String::class.java) } - suspend fun postNB(path: String, request: Any, - additionalHeaders: Map<String, String>?): String { + suspend fun postNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?): WebClientResponse<String> { return postNB(path, request, additionalHeaders, String::class.java) } - suspend fun <T> postNB(path: String, request: Any, - additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = - withContext(Dispatchers.IO) { - val httpPost = HttpPost(host(path)) - httpPost.entity = StringEntity(strRequest(request)) - httpPost.setHeaders(basicHeaders(additionalHeaders)) - httpClientNB().execute(httpPost).entity.content.use { - getResponse(it, responseType) - } - } - - suspend fun putNB(path: String, request: Any): String { + suspend fun <T> postNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?, + responseType: Class<T>): WebClientResponse<T> = + withContext(Dispatchers.IO) { + post(path, request, additionalHeaders!!, responseType) + } + + suspend fun putNB(path: String, request: Any): WebClientResponse<String> { return putNB(path, request, null, String::class.java) } suspend fun putNB(path: String, request: Any, - additionalHeaders: Map<String, String>?): String { + additionalHeaders: Array<BasicHeader>?): WebClientResponse<String> { return putNB(path, request, additionalHeaders, String::class.java) } suspend fun <T> putNB(path: String, request: Any, - additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = - withContext(Dispatchers.IO) { - val httpPut = HttpPut(host(path)) - httpPut.entity = StringEntity(strRequest(request)) - httpPut.setHeaders(basicHeaders(additionalHeaders)) - httpClientNB().execute(httpPut).entity.content.use { - getResponse(it, responseType) + additionalHeaders: Array<BasicHeader>?, + responseType: Class<T>): WebClientResponse<T> = + withContext(Dispatchers.IO) { + put(path, request, additionalHeaders!!, responseType) } - } - suspend fun <T> deleteNB(path: String): String { + suspend fun <T> deleteNB(path: String): WebClientResponse<String> { return deleteNB(path, null, String::class.java) } - suspend fun <T> deleteNB(path: String, - additionalHeaders: Map<String, String>?): String { + suspend fun <T> deleteNB(path: String, additionalHeaders: Array<BasicHeader>?): + WebClientResponse<String> { return deleteNB(path, additionalHeaders, String::class.java) } - suspend fun <T> deleteNB(path: String, - additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = - withContext(Dispatchers.IO) { - val httpDelete = HttpDelete(host(path)) - httpDelete.setHeaders(basicHeaders(additionalHeaders)) - httpClient().execute(httpDelete).entity.content.use { - getResponse(it, responseType) + suspend fun <T> deleteNB(path: String, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>): + WebClientResponse<T> = + withContext(Dispatchers.IO) { + delete(path, additionalHeaders!!, responseType) } - } - suspend fun <T> patchNB(path: String, request: Any, - additionalHeaders: Map<String, String>?, - responseType: Class<T>): T = - withContext(Dispatchers.IO) { - val httpPatch = HttpPatch(host(path)) - httpPatch.entity = StringEntity(strRequest(request)) - httpPatch.setHeaders(basicHeaders(additionalHeaders)) - httpClient().execute(httpPatch).entity.content.use { - getResponse(it, responseType) + suspend fun <T> patchNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>): + WebClientResponse<T> = + withContext(Dispatchers.IO) { + patch(path, request, additionalHeaders!!, responseType) } - } - suspend fun exchangeNB(methodType: String, path: String, request: Any): - String { + suspend fun exchangeNB(methodType: String, path: String, request: Any): WebClientResponse<String> { return exchangeNB(methodType, path, request, hashMapOf(), - String::class.java) + String::class.java) } - suspend fun exchangeNB(methodType: String, path: String, request: Any, - additionalHeaders: Map<String, String>?): String { - return exchangeNB(methodType, path, request, additionalHeaders, - String::class.java) + suspend fun exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?): + WebClientResponse<String> { + return exchangeNB(methodType, path, request, additionalHeaders, String::class.java) } suspend fun <T> exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?, - responseType: Class<T>): T { + responseType: Class<T>): WebClientResponse<T> { + //TODO: possible inconsistency + //NOTE: this basic headers function is different from non-blocking + val convertedHeaders: Array<BasicHeader> = basicHeaders(additionalHeaders!!) return when (HttpMethod.resolve(methodType)) { - HttpMethod.GET -> getNB(path, additionalHeaders, responseType) - HttpMethod.POST -> postNB(path, request, additionalHeaders, - responseType) - HttpMethod.DELETE -> deleteNB(path, additionalHeaders, responseType) - HttpMethod.PUT -> putNB(path, request, additionalHeaders, - responseType) - HttpMethod.PATCH -> patchNB(path, request, additionalHeaders, - responseType) + HttpMethod.GET -> getNB(path, convertedHeaders, responseType) + HttpMethod.POST -> postNB(path, request, convertedHeaders, responseType) + HttpMethod.DELETE -> deleteNB(path, convertedHeaders, responseType) + HttpMethod.PUT -> putNB(path, request, convertedHeaders, responseType) + HttpMethod.PATCH -> patchNB(path, request, convertedHeaders, responseType) else -> throw BluePrintProcessorException("Unsupported method" + - "Type($methodType)") + "Type($methodType)") } } @@ -266,10 +246,9 @@ interface BlueprintWebClientService { } private fun basicHeaders(headers: Map<String, String>?): - Array<BasicHeader> { - + Array<BasicHeader> { val basicHeaders = mutableListOf<BasicHeader>() - defaultHeaders().forEach { name, value -> + defaultHeaders().forEach { (name, value) -> basicHeaders.add(BasicHeader(name, value)) } headers?.forEach { name, value -> @@ -281,8 +260,11 @@ interface BlueprintWebClientService { // Non Blocking Rest Implementation suspend fun httpClientNB(): CloseableHttpClient { return HttpClients.custom() - .addInterceptorFirst(WebClientUtils.logRequest()) - .addInterceptorLast(WebClientUtils.logResponse()) - .build() + .addInterceptorFirst(WebClientUtils.logRequest()) + .addInterceptorLast(WebClientUtils.logResponse()) + .build() } -}
\ No newline at end of file + + //TODO maybe there could be cases where we care about return headers? + data class WebClientResponse<T>(val status: Int, val body: T) +} diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt index 93eb12dd0..21d05e620 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/RestClientServiceTest.kt @@ -99,7 +99,7 @@ class RestClientServiceTest { .blueprintWebClientService("sample") val response = restClientService.exchangeResource( HttpMethod.PATCH.name, "/sample/name", "") - assertEquals("Patch request successful", response, + assertEquals("Patch request successful", response.body, "failed to get patch response") } @@ -111,7 +111,7 @@ class RestClientServiceTest { headers["X-Transaction-Id"] = "1234" val response = restClientService.exchangeResource(HttpMethod.GET.name, "/sample/name", "") - assertNotNull(response, "failed to get response") + assertNotNull(response.body, "failed to get response") } @Test @@ -130,7 +130,7 @@ class RestClientServiceTest { runBlocking { val get = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.GET.name, - "/sample/basic", "")} + "/sample/basic", "").body} get.start() res = get.await() } @@ -163,32 +163,32 @@ class RestClientServiceTest { val get1 = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.GET.name, "/sample/aai/v14/business/customers", "", headers, - Customer::class.java)} + Customer::class.java).body} val get2 = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.GET.name, "/sample/aai/v14/business/customers", "", headers, - Customer::class.java)} + Customer::class.java).body} val post = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.POST.name, "/sample/aai/v14/business/customers", post1, headers, - String::class.java)} + String::class.java).body} val put = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.PUT.name, "/sample/aai/v14/business/customers", post1, headers, - String::class.java)} + String::class.java).body} val patch = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.PATCH.name, "/sample/aai/v14/business/customers", post1, headers, - String::class.java)} + String::class.java).body} val delete = async(start = CoroutineStart.LAZY) { restClientService.exchangeNB(HttpMethod.DELETE.name, "/sample/aai/v14/business/customers", "", headers, - String::class.java)} + String::class.java).body} get1.start() get2.start() @@ -346,7 +346,7 @@ class HttpServer { fun servletContainer(): ServletWebServerFactory { val connector = Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL) - connector.setPort(8080) + connector.port = 8080 val tomcat = TomcatServletWebServerFactory() tomcat.addAdditionalTomcatConnectors(connector) @@ -361,4 +361,4 @@ data class Customer( val id: String, val name: String, val type: String, - val resource: String)
\ No newline at end of file + val resource: String) |