11package {{ sdk .namespace | caseDot }}
22
3- import com.google.gson.Gson
3+ import com.google.gson.GsonBuilder
4+ import com.google.gson.reflect.TypeToken
45import {{ sdk .namespace | caseDot }}.exceptions.{{ spec .title | caseUcfirst }}Exception
56import {{ sdk .namespace | caseDot }}.extensions.fromJson
7+ import {{ sdk .namespace | caseDot }}.json.PreciseNumberAdapter
68import kotlinx.coroutines.CoroutineScope
79import kotlinx.coroutines.Dispatchers
810import kotlinx.coroutines.Job
@@ -14,6 +16,7 @@ import okhttp3.MediaType.Companion.toMediaType
1416import okhttp3.RequestBody.Companion.asRequestBody
1517import okhttp3.RequestBody.Companion.toRequestBody
1618import okhttp3.logging.HttpLoggingInterceptor
19+ import java.io.BufferedInputStream
1720import java.io.BufferedReader
1821import java.io.File
1922import java.io.IOException
@@ -37,12 +40,18 @@ class Client @JvmOverloads constructor(
3740
3841 private val job = Job()
3942
40- private lateinit var http: OkHttpClient
43+ private val gson = GsonBuilder().registerTypeAdapter(
44+ object : TypeToken<Map <String , Any >>(){}.type,
45+ PreciseNumberAdapter()
46+ ).create()
47+
48+ lateinit var http: OkHttpClient
4149
4250 private val headers: MutableMap<String , String >
43-
51+
4452 val config: MutableMap<String , String >
4553
54+
4655 init {
4756 headers = mutableMapOf(
4857 "content-type" to "application/json",
@@ -54,7 +63,7 @@ class Client @JvmOverloads constructor(
5463
5564 )
5665 config = mutableMapOf()
57-
66+
5867 setSelfSigned(selfSigned)
5968 }
6069
@@ -79,10 +88,10 @@ class Client @JvmOverloads constructor(
7988{% endfor %}
8089 /**
8190 * Set self Signed
82- *
91+ *
8392 * @param status
8493 *
85- * @return this
94+ * @return this
8695 */
8796 fun setSelfSigned(status: Boolean): Client {
8897 selfSigned = status
@@ -98,9 +107,12 @@ class Client @JvmOverloads constructor(
98107 try {
99108 // Create a trust manager that does not validate certificate chains
100109 val trustAllCerts = arrayOf<TrustManager >(
110+ @Suppress("CustomX509TrustManager")
101111 object : X509TrustManager {
112+ @Suppress("TrustAllX509TrustManager")
102113 override fun checkClientTrusted(chain: Array<X509Certificate >, authType: String) {
103114 }
115+ @Suppress("TrustAllX509TrustManager")
104116 override fun checkServerTrusted(chain: Array<X509Certificate >, authType: String) {
105117 }
106118 override fun getAcceptedIssuers(): Array<X509Certificate > {
@@ -139,11 +151,11 @@ class Client @JvmOverloads constructor(
139151
140152 /**
141153 * Add Header
142- *
154+ *
143155 * @param key
144156 * @param value
145157 *
146- * @return this
158+ * @return this
147159 */
148160 fun addHeader(key: String, value: String): Client {
149161 headers[key] = value
@@ -152,22 +164,23 @@ class Client @JvmOverloads constructor(
152164
153165 /**
154166 * Send the HTTP request
155- *
167+ *
156168 * @param method
157169 * @param path
158170 * @param headers
159171 * @param params
160172 *
161- * @return [Response]
173+ * @return [Response]
162174 */
163175 @Throws({{ spec .title | caseUcfirst }}Exception::class)
164- suspend fun call(
165- method: String,
166- path: String,
167- headers: Map<String , String > = mapOf(),
168- params: Map<String , Any ?> = mapOf()
169- ): Response {
170-
176+ suspend fun <T > call(
177+ method: String,
178+ path: String,
179+ headers: Map<String , String > = mapOf(),
180+ params: Map<String , Any ?> = mapOf(),
181+ responseType: Class<T >,
182+ convert: ((Map<String , Any ,>) -> T)? = null
183+ ): T {
171184 val filteredParams = params.filterValues { it != null }
172185
173186 val requestHeaders = this.headers.toHeaders().newBuilder()
@@ -202,7 +215,7 @@ class Client @JvmOverloads constructor(
202215 .get()
203216 .build()
204217
205- return awaitResponse(request)
218+ return awaitResponse(request, responseType, convert )
206219 }
207220
208221 val body = if (MultipartBody.FORM.toString() == headers["content-type"]) {
@@ -230,7 +243,7 @@ class Client @JvmOverloads constructor(
230243 }
231244 builder.build()
232245 } else {
233- Gson() .toJson(filteredParams)
246+ gson .toJson(filteredParams)
234247 .toRequestBody("application/json".toMediaType())
235248 }
236249
@@ -240,21 +253,24 @@ class Client @JvmOverloads constructor(
240253 .method(method, body)
241254 .build()
242255
243- return awaitResponse(request)
256+ return awaitResponse(request, responseType, convert )
244257 }
245258
246259 /**
247260 * Await Response
248- *
249- * @param method
250- * @param path
251- * @param headers
252- * @param params
253261 *
254- * @return [Response]
262+ * @param request
263+ * @param responseType
264+ * @param convert
265+ *
266+ * @return [T]
255267 */
256268 @Throws({{ spec .title | caseUcfirst }}Exception::class)
257- private suspend fun awaitResponse(request: Request) = suspendCancellableCoroutine<Response > {
269+ private suspend fun <T > awaitResponse(
270+ request: Request,
271+ responseType: Class<T >,
272+ convert: ((Map<String , Any ,>) -> T)? = null
273+ ) = suspendCancellableCoroutine<T > {
258274 http.newCall(request).enqueue(object : Callback {
259275 override fun onFailure(call: Call, e: IOException) {
260276 if (it.isCancelled) {
@@ -263,23 +279,55 @@ class Client @JvmOverloads constructor(
263279 it.cancel(e)
264280 }
265281
282+ @Suppress("UNCHECKED_CAST")
266283 override fun onResponse(call: Call, response: Response) {
267- if (response.code >= 400) {
268- val bodyString = response.body
269- ?.charStream()
270- ?.buffered()
271- ?.use(BufferedReader::readText) ?: ""
272-
273- val contentType: String = response.headers["content-type"] ?: ""
274- val error = if (contentType.contains("application/json", ignoreCase = true)) {
275- bodyString.fromJson()
284+ if (!response.isSuccessful) {
285+ val body = response.body!!
286+ .charStream()
287+ .buffered()
288+ .use(BufferedReader::readText)
289+ val error = if (response.headers["content-type"]?.contains("application/json") == true) {
290+ body.fromJson()
276291 } else {
277- {{ spec .title | caseUcfirst }}Exception(bodyString , response.code)
292+ {{ spec .title | caseUcfirst }}Exception(body , response.code)
278293 }
279294 it.cancel(error)
295+ return
296+ }
297+ when {
298+ responseType == Boolean::class.java -> {
299+ it.resume(true as T)
300+ return
301+ }
302+ responseType == ByteArray::class.java -> {
303+ it.resume(response.body!!
304+ .byteStream()
305+ .buffered()
306+ .use(BufferedInputStream::readBytes) as T
307+ )
308+ return
309+ }
310+ response.body == null -> {
311+ it.resume(true as T)
312+ return
313+ }
314+ }
315+ val body = response.body!!
316+ .charStream()
317+ .buffered()
318+ .use(BufferedReader::readText)
319+ if (body.isEmpty()) {
320+ it.resume(true as T)
321+ return
280322 }
281- it.resume(response)
323+ val map = gson.fromJson<Map <String , Any >>(
324+ body,
325+ object : TypeToken<Map <String , Any >>(){}.type
326+ )
327+ it.resume(
328+ convert?.invoke(map) ?: map as T
329+ )
282330 }
283331 })
284332 }
285- }
333+ }
0 commit comments