2 * Copyright © 2017-2019 AT&T, Bell Canada, Nordix Foundation
3 * Modifications Copyright © 2018-2019 IBM.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
20 import com.fasterxml.jackson.databind.JsonNode
21 import kotlinx.coroutines.Dispatchers
22 import kotlinx.coroutines.withContext
23 import org.apache.commons.io.IOUtils
24 import org.apache.http.client.methods.*
25 import org.apache.http.entity.StringEntity
26 import org.apache.http.impl.client.CloseableHttpClient
27 import org.apache.http.impl.client.HttpClients
28 import org.apache.http.message.BasicHeader
29 import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
30 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
31 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
32 import org.springframework.http.HttpMethod
33 import java.nio.charset.Charset
35 interface BlueprintWebClientService {
37 fun defaultHeaders(): Map<String, String>
39 fun host(uri: String): String
41 fun httpClient(): CloseableHttpClient {
42 return HttpClients.custom()
43 .addInterceptorFirst(WebClientUtils.logRequest())
44 .addInterceptorLast(WebClientUtils.logResponse())
48 fun exchangeResource(methodType: String, path: String, request: String): String {
49 return this.exchangeResource(methodType, path, request, defaultHeaders())
52 fun exchangeResource(methodType: String, path: String, request: String, headers: Map<String, String>): String {
53 val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders(headers)
54 return when (HttpMethod.resolve(methodType)) {
55 HttpMethod.DELETE -> delete(path, convertedHeaders)
56 HttpMethod.GET -> get(path, convertedHeaders)
57 HttpMethod.POST -> post(path, request, convertedHeaders)
58 HttpMethod.PUT -> put(path, request, convertedHeaders)
59 HttpMethod.PATCH -> patch(path, request, convertedHeaders)
60 else -> throw BluePrintProcessorException("Unsupported methodType($methodType)")
64 fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
65 return headers.map{ BasicHeader(it.key, it.value)}.toTypedArray()
68 fun delete(path: String, headers: Array<BasicHeader>): String {
69 val httpDelete = HttpDelete(host(path))
70 httpDelete.setHeaders(headers)
71 httpClient().execute(httpDelete).entity.content.use {
72 return IOUtils.toString(it, Charset.defaultCharset())
76 fun get(path: String, headers: Array<BasicHeader>): String {
77 val httpGet = HttpGet(host(path))
78 httpGet.setHeaders(headers)
79 httpClient().execute(httpGet).entity.content.use {
80 return IOUtils.toString(it, Charset.defaultCharset())
84 fun post(path: String, request: String, headers: Array<BasicHeader>): String {
85 val httpPost = HttpPost(host(path))
86 val entity = StringEntity(request)
87 httpPost.entity = entity
88 httpPost.setHeaders(headers)
89 httpClient().execute(httpPost).entity.content.use {
90 return IOUtils.toString(it, Charset.defaultCharset())
94 fun put(path: String, request: String, headers: Array<BasicHeader>): String {
95 val httpPut = HttpPut(host(path))
96 val entity = StringEntity(request)
97 httpPut.entity = entity
98 httpPut.setHeaders(headers)
99 httpClient().execute(httpPut).entity.content.use {
100 return IOUtils.toString(it, Charset.defaultCharset())
104 fun patch(path: String, request: String, headers: Array<BasicHeader>): String {
105 val httpPatch = HttpPatch(host(path))
106 val entity = StringEntity(request)
107 httpPatch.entity = entity
108 httpPatch.setHeaders(headers)
109 httpClient().execute(httpPatch).entity.content.use {
110 return IOUtils.toString(it, Charset.defaultCharset())
114 // Non Blocking Rest Implementation
115 suspend fun httpClientNB(): CloseableHttpClient {
116 return HttpClients.custom()
117 .addInterceptorFirst(WebClientUtils.logRequest())
118 .addInterceptorLast(WebClientUtils.logResponse())
122 suspend fun getNB(path: String): String {
123 return getNB(path, null, String::class.java)
126 suspend fun getNB(path: String, additionalHeaders: Map<String, String>?): String {
127 return getNB(path, additionalHeaders, String::class.java)
130 suspend fun <T> getNB(path: String, additionalHeaders: Map<String, String>?,
131 responseType: Class<T>): T = withContext(Dispatchers.IO) {
132 val httpGet = HttpGet(host(path))
133 httpGet.setHeaders(basicHeaders(additionalHeaders))
134 httpClientNB().execute(httpGet).entity.content.use {
135 JacksonUtils.readValue(it, responseType)!!
139 suspend fun postNB(path: String, request: Any): String {
140 return postNB(path, request, null, String::class.java)
143 suspend fun postNB(path: String, request: Any, additionalHeaders: Map<String, String>?): String {
144 return postNB(path, request, additionalHeaders, String::class.java)
147 suspend fun <T> postNB(path: String, request: Any, additionalHeaders: Map<String, String>?,
148 responseType: Class<T>): T =
149 withContext(Dispatchers.IO) {
150 val httpPost = HttpPost(host(path))
151 httpPost.entity = StringEntity(strRequest(request))
152 httpPost.setHeaders(basicHeaders(additionalHeaders))
153 httpClientNB().execute(httpPost).entity.content.use {
154 JacksonUtils.readValue(it, responseType)!!
158 suspend fun putNB(path: String, request: Any): String {
159 return putNB(path, request, null, String::class.java)
162 suspend fun putNB(path: String, request: Any, additionalHeaders: Map<String, String>?): String {
163 return putNB(path, request, additionalHeaders, String::class.java)
166 suspend fun <T> putNB(path: String, request: Any, additionalHeaders: Map<String, String>?,
167 responseType: Class<T>): T = withContext(Dispatchers.IO) {
168 val httpPut = HttpPut(host(path))
169 httpPut.entity = StringEntity(strRequest(request))
170 httpPut.setHeaders(basicHeaders(additionalHeaders))
171 httpClientNB().execute(httpPut).entity.content.use {
172 JacksonUtils.readValue(it, responseType)!!
176 suspend fun <T> deleteNB(path: String): String {
177 return deleteNB(path, null, String::class.java)
180 suspend fun <T> deleteNB(path: String, additionalHeaders: Map<String, String>?): String {
181 return deleteNB(path, additionalHeaders, String::class.java)
184 suspend fun <T> deleteNB(path: String, additionalHeaders: Map<String, String>?, responseType: Class<T>): T =
185 withContext(Dispatchers.IO) {
186 val httpDelete = HttpDelete(host(path))
187 httpDelete.setHeaders(basicHeaders(additionalHeaders))
188 httpClient().execute(httpDelete).entity.content.use {
189 JacksonUtils.readValue(it, responseType)!!
193 suspend fun <T> patchNB(path: String, request: Any, additionalHeaders: Map<String, String>?,
194 responseType: Class<T>): T = withContext(Dispatchers.IO) {
195 val httpPatch = HttpPatch(host(path))
196 httpPatch.entity = StringEntity(strRequest(request))
197 httpPatch.setHeaders(basicHeaders(additionalHeaders))
198 httpClient().execute(httpPatch).entity.content.use {
199 JacksonUtils.readValue(it, responseType)!!
203 suspend fun exchangeNB(methodType: String, path: String, request: Any): String {
204 return exchangeNB(methodType, path, request, hashMapOf(), String::class.java)
207 suspend fun exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?): String {
208 return exchangeNB(methodType, path, request, additionalHeaders, String::class.java)
211 suspend fun <T> exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?,
212 responseType: Class<T>): T {
213 return when (HttpMethod.resolve(methodType)) {
214 HttpMethod.GET -> getNB(path, additionalHeaders, responseType)
215 HttpMethod.POST -> postNB(path, request, additionalHeaders, responseType)
216 HttpMethod.DELETE -> deleteNB(path, additionalHeaders, responseType)
217 HttpMethod.PUT -> putNB(path, request, additionalHeaders, responseType)
218 HttpMethod.PATCH -> patchNB(path, request, additionalHeaders, responseType)
219 else -> throw BluePrintProcessorException("Unsupported methodType($methodType)")
223 private fun strRequest(request: Any): String {
224 return when (request) {
225 is String -> request.toString()
226 is JsonNode -> request.toString()
227 else -> JacksonUtils.getJson(request)
231 private fun basicHeaders(headers: Map<String, String>?): Array<BasicHeader> {
232 val basicHeaders = mutableListOf<BasicHeader>()
233 defaultHeaders().forEach { name, value ->
234 basicHeaders.add(BasicHeader(name, value))
236 headers?.forEach { name, value ->
237 basicHeaders.add(BasicHeader(name, value))
239 return basicHeaders.toTypedArray()