2 * Copyright © 2017-2019 AT&T, Bell Canada, Nordix Foundation
3 * Modifications Copyright © 2018-2019 IBM.
4 * Modifications Copyright © 2019 Huawei.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
21 import com.fasterxml.jackson.databind.JsonNode
22 import kotlinx.coroutines.Dispatchers
23 import kotlinx.coroutines.withContext
24 import org.apache.commons.io.IOUtils
25 import org.apache.http.client.methods.HttpDelete
26 import org.apache.http.client.methods.HttpGet
27 import org.apache.http.client.methods.HttpPatch
28 import org.apache.http.client.methods.HttpPost
29 import org.apache.http.client.methods.HttpPut
30 import org.apache.http.entity.StringEntity
31 import org.apache.http.impl.client.CloseableHttpClient
32 import org.apache.http.impl.client.HttpClients
33 import org.apache.http.message.BasicHeader
34 import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
35 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
36 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
37 import org.springframework.http.HttpMethod
38 import java.io.InputStream
39 import java.nio.charset.Charset
41 interface BlueprintWebClientService {
43 fun defaultHeaders(): Map<String, String>
45 fun host(uri: String): String
47 fun httpClient(): CloseableHttpClient {
48 return HttpClients.custom()
49 .addInterceptorFirst(WebClientUtils.logRequest())
50 .addInterceptorLast(WebClientUtils.logResponse())
54 fun exchangeResource(methodType: String, path: String, request: String):
56 return this.exchangeResource(methodType, path, request,
60 fun exchangeResource(methodType: String, path: String, request: String,
61 headers: Map<String, String>): String {
62 val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders(
64 return when (HttpMethod.resolve(methodType)) {
65 HttpMethod.DELETE -> delete(path, convertedHeaders)
66 HttpMethod.GET -> get(path, convertedHeaders)
67 HttpMethod.POST -> post(path, request, convertedHeaders)
68 HttpMethod.PUT -> put(path, request, convertedHeaders)
69 HttpMethod.PATCH -> patch(path, request, convertedHeaders)
70 else -> throw BluePrintProcessorException("Unsupported met" +
71 "hodType($methodType)")
75 fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
76 return headers.map{ BasicHeader(it.key, it.value)}.toTypedArray()
79 fun delete(path: String, headers: Array<BasicHeader>): String {
80 val httpDelete = HttpDelete(host(path))
81 httpDelete.setHeaders(headers)
82 httpClient().execute(httpDelete).entity.content.use {
83 return IOUtils.toString(it, Charset.defaultCharset())
87 fun get(path: String, headers: Array<BasicHeader>): String {
88 val httpGet = HttpGet(host(path))
89 httpGet.setHeaders(headers)
90 httpClient().execute(httpGet).entity.content.use {
91 return IOUtils.toString(it, Charset.defaultCharset())
95 fun post(path: String, request: String, headers: Array<BasicHeader>):
97 val httpPost = HttpPost(host(path))
98 val entity = StringEntity(request)
99 httpPost.entity = entity
100 httpPost.setHeaders(headers)
101 httpClient().execute(httpPost).entity.content.use {
102 return IOUtils.toString(it, Charset.defaultCharset())
106 fun put(path: String, request: String, headers: Array<BasicHeader>):
108 val httpPut = HttpPut(host(path))
109 val entity = StringEntity(request)
110 httpPut.entity = entity
111 httpPut.setHeaders(headers)
112 httpClient().execute(httpPut).entity.content.use {
113 return IOUtils.toString(it, Charset.defaultCharset())
117 fun patch(path: String, request: String, headers: Array<BasicHeader>):
119 val httpPatch = HttpPatch(host(path))
120 val entity = StringEntity(request)
121 httpPatch.entity = entity
122 httpPatch.setHeaders(headers)
123 httpClient().execute(httpPatch).entity.content.use {
124 return IOUtils.toString(it, Charset.defaultCharset())
129 suspend fun getNB(path: String): String {
130 return getNB(path, null, String::class.java)
133 suspend fun getNB(path: String, additionalHeaders: Map<String, String>?):
135 return getNB(path, additionalHeaders, String::class.java)
138 suspend fun <T> getNB(path: String, additionalHeaders: Map<String, String>?,
139 responseType: Class<T>): T =
140 withContext(Dispatchers.IO) {
141 val httpGet = HttpGet(host(path))
142 httpGet.setHeaders(basicHeaders(additionalHeaders))
143 httpClientNB().execute(httpGet).entity.content.use {
144 getResponse(it, responseType)
148 suspend fun postNB(path: String, request: Any): String {
149 return postNB(path, request, null, String::class.java)
152 suspend fun postNB(path: String, request: Any,
153 additionalHeaders: Map<String, String>?): String {
154 return postNB(path, request, additionalHeaders, String::class.java)
157 suspend fun <T> postNB(path: String, request: Any,
158 additionalHeaders: Map<String, String>?,
159 responseType: Class<T>): T =
160 withContext(Dispatchers.IO) {
161 val httpPost = HttpPost(host(path))
162 httpPost.entity = StringEntity(strRequest(request))
163 httpPost.setHeaders(basicHeaders(additionalHeaders))
164 httpClientNB().execute(httpPost).entity.content.use {
165 getResponse(it, responseType)
169 suspend fun putNB(path: String, request: Any): String {
170 return putNB(path, request, null, String::class.java)
173 suspend fun putNB(path: String, request: Any,
174 additionalHeaders: Map<String, String>?): String {
175 return putNB(path, request, additionalHeaders, String::class.java)
178 suspend fun <T> putNB(path: String, request: Any,
179 additionalHeaders: Map<String, String>?,
180 responseType: Class<T>): T =
181 withContext(Dispatchers.IO) {
182 val httpPut = HttpPut(host(path))
183 httpPut.entity = StringEntity(strRequest(request))
184 httpPut.setHeaders(basicHeaders(additionalHeaders))
185 httpClientNB().execute(httpPut).entity.content.use {
186 getResponse(it, responseType)
190 suspend fun <T> deleteNB(path: String): String {
191 return deleteNB(path, null, String::class.java)
194 suspend fun <T> deleteNB(path: String,
195 additionalHeaders: Map<String, String>?): String {
196 return deleteNB(path, additionalHeaders, String::class.java)
199 suspend fun <T> deleteNB(path: String,
200 additionalHeaders: Map<String, String>?,
201 responseType: Class<T>): T =
202 withContext(Dispatchers.IO) {
203 val httpDelete = HttpDelete(host(path))
204 httpDelete.setHeaders(basicHeaders(additionalHeaders))
205 httpClient().execute(httpDelete).entity.content.use {
206 getResponse(it, responseType)
210 suspend fun <T> patchNB(path: String, request: Any,
211 additionalHeaders: Map<String, String>?,
212 responseType: Class<T>): T =
213 withContext(Dispatchers.IO) {
214 val httpPatch = HttpPatch(host(path))
215 httpPatch.entity = StringEntity(strRequest(request))
216 httpPatch.setHeaders(basicHeaders(additionalHeaders))
217 httpClient().execute(httpPatch).entity.content.use {
218 getResponse(it, responseType)
222 suspend fun exchangeNB(methodType: String, path: String, request: Any):
224 return exchangeNB(methodType, path, request, hashMapOf(),
228 suspend fun exchangeNB(methodType: String, path: String, request: Any,
229 additionalHeaders: Map<String, String>?): String {
230 return exchangeNB(methodType, path, request, additionalHeaders,
234 suspend fun <T> exchangeNB(methodType: String, path: String, request: Any,
235 additionalHeaders: Map<String, String>?,
236 responseType: Class<T>): T {
238 return when (HttpMethod.resolve(methodType)) {
239 HttpMethod.GET -> getNB(path, additionalHeaders, responseType)
240 HttpMethod.POST -> postNB(path, request, additionalHeaders,
242 HttpMethod.DELETE -> deleteNB(path, additionalHeaders, responseType)
243 HttpMethod.PUT -> putNB(path, request, additionalHeaders,
245 HttpMethod.PATCH -> patchNB(path, request, additionalHeaders,
247 else -> throw BluePrintProcessorException("Unsupported method" +
252 private fun strRequest(request: Any): String {
253 return when (request) {
254 is String -> request.toString()
255 is JsonNode -> request.toString()
256 else -> JacksonUtils.getJson(request)
260 private fun <T> getResponse(it: InputStream, responseType: Class<T>): T {
261 return if (responseType == String::class.java) {
262 IOUtils.toString(it, Charset.defaultCharset()) as T
264 JacksonUtils.readValue(it, responseType)!!
268 private fun basicHeaders(headers: Map<String, String>?):
271 val basicHeaders = mutableListOf<BasicHeader>()
272 defaultHeaders().forEach { name, value ->
273 basicHeaders.add(BasicHeader(name, value))
275 headers?.forEach { name, value ->
276 basicHeaders.add(BasicHeader(name, value))
278 return basicHeaders.toTypedArray()
281 // Non Blocking Rest Implementation
282 suspend fun httpClientNB(): CloseableHttpClient {
283 return HttpClients.custom()
284 .addInterceptorFirst(WebClientUtils.logRequest())
285 .addInterceptorLast(WebClientUtils.logResponse())