All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.lt.lazy_people_http.call.RealCall.kt Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package com.lt.lazy_people_http.call

import com.lt.lazy_people_http.call.adapter.SuspendHook
import com.lt.lazy_people_http.config.CustomConfigsNode
import com.lt.lazy_people_http.config.LazyPeopleHttpConfig
import com.lt.lazy_people_http.config.ParameterLocation
import com.lt.lazy_people_http.request.RequestInfo
import com.lt.lazy_people_http.type.JsonString
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.FormDataContent
import io.ktor.client.request.parameter
import io.ktor.client.request.request
import io.ktor.client.request.setBody
import io.ktor.client.request.url
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.bodyAsText
import io.ktor.http.Parameters
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * creator: lt  2023/3/10  [email protected]
 * effect : 进行http请求
 * warning:
 */
class RealCall(
    val config: LazyPeopleHttpConfig,
    val info: RequestInfo,
) : Call {
    private var customConfigs: CustomConfigsNode? = null

    override fun enqueue(callback: Callback, scope: CoroutineScope) =
        scope.launch(Dispatchers.Main) {
            try {
                callback.onResponse(this@RealCall, getData())
            } catch (e: Exception) {
                if (e is CancellationException)
                    throw e
                callback.onFailure(this@RealCall, e)
            }
        }

    override suspend fun await(): T = try {
        val hook = config.suspendHooks.find { it.whetherToHook(config, info) } as? SuspendHook
        if (hook == null)
            getData()
        else
            hook.hook(config, info, this, ::getData)
    } catch (e: Exception) {
        if (e is CancellationException)
            throw e
        config.onSuspendError(e, info)
    }

    override fun config(block: HttpRequestBuilder.() -> Unit): Call {
        val next = CustomConfigsNode(block)
        val config = customConfigs
        if (config == null)
            customConfigs = next
        else
            config.next = next
        return this
    }

    private suspend fun getData(
        config: LazyPeopleHttpConfig = this.config,
        info: RequestInfo = this.info,
    ): T = withContext(Dispatchers.Default) {
        //创建请求对象
        val builder: HttpRequestBuilder.() -> Unit = {
            //设置请求方法
            method = (info.requestMethod ?: config.defaultRequestMethod).method
            //设置请求地址
            url(config.encryptor.encrypt(info.url, ParameterLocation.Url, info))
            //传递Query参数
            info.parameters?.let { array ->
                for (i in array.indices step 2) {
                    val key = config.encryptor.encrypt(
                        array[i] ?: throw RuntimeException("${info.url} parameters key is null"),
                        ParameterLocation.ParameterKey,
                        info
                    )
                    val value = config.encryptor.encrypt(
                        array[i + 1] ?: "",
                        ParameterLocation.ParameterValue,
                        info
                    )
                    parameter(key, value)
                }
            }
            //传递Field参数
            info.formParameters?.let { array ->
                setBody(FormDataContent(Parameters.build {
                    for (i in array.indices step 2) {
                        val key = config.encryptor.encrypt(
                            array[i]
                                ?: throw RuntimeException("${info.url} formParameters key is null"),
                            ParameterLocation.ParameterKey,
                            info
                        )
                        val value = config.encryptor.encrypt(
                            array[i + 1] ?: "",
                            ParameterLocation.ParameterValue,
                            info
                        )
                        append(key, value)
                    }
                }))
            }
            //增加请求头
            info.headers?.let { array ->
                for (i in array.indices step 2) {
                    val key = config.encryptor.encrypt(array[i], ParameterLocation.HeaderKey, info)
                    val value =
                        config.encryptor.encrypt(array[i + 1], ParameterLocation.HeaderValue, info)
                    headers.append(key, value)
                }
            }
            //处理全局和单独的自定义配置
            config.onRequest?.invoke(this, info)
            var config = customConfigs
            while (config != null) {
                config.block(this)
                config = config.next
            }
        }
        val response: HttpResponse = config.client.request(builder)
        //接收返回值
        val result = response.bodyAsText()
        config.onResponse?.invoke(response, info, result)
        val json = config.encryptor.decrypt(result, ParameterLocation.Result, info)
        //将返回的json序列化为指定对象
        return@withContext if (info.returnType.classifier == JsonString::class)
            JsonString(json) as T
        else
            config.serializer.decodeFromString(json, info.returnType) as T
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy