All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
commonMain.com.lt.lazy_people_http.call.RealCall.kt Maven / Gradle / Ivy
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
}
}