refactor of Ktor calls

This commit is contained in:
InsanusMokrassar 2019-04-26 11:12:01 +08:00
parent 711410c426
commit c12d08eda8
5 changed files with 76 additions and 55 deletions

View File

@ -7,6 +7,8 @@ some default library
* All proxy help methods was removed . They are will be replaced in separated project * All proxy help methods was removed . They are will be replaced in separated project
* `Ktor` version `1.1.3` -> `1.1.4` * `Ktor` version `1.1.3` -> `1.1.4`
* Requests results now always decoding as `UTF-8` * Requests results now always decoding as `UTF-8`
* `AbstractRequestCallFactory` was added with cache of methods urls to avoid memory leaks
* Small refactoring of work with response in `KtorRequestsExecutor`
## 0.13.0 Telegram Polls ## 0.13.0 Telegram Polls

View File

@ -60,7 +60,9 @@ class KtorRequestsExecutor(
if (call == null) { if (call == null) {
throw IllegalArgumentException("Can't execute request: $request") throw IllegalArgumentException("Can't execute request: $request")
} }
val content = call.response.content.toByteArray().toString(Charsets.UTF_8) val content = call.response.use {
it.content.toByteArray().toString(Charsets.UTF_8)
}
val responseObject = jsonFormatter.parse( val responseObject = jsonFormatter.parse(
Response.serializer(request.resultSerializer()), Response.serializer(request.resultSerializer()),
content content

View File

@ -0,0 +1,41 @@
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorCallFactory
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import io.ktor.client.HttpClient
import io.ktor.client.call.HttpClientCall
import io.ktor.client.call.call
import io.ktor.client.request.accept
import io.ktor.client.request.url
import io.ktor.http.ContentType
import io.ktor.http.HttpMethod
abstract class AbstractRequestCallFactory : KtorCallFactory {
private val methodsCache: MutableMap<String, String> = mutableMapOf()
override suspend fun <T : Any> prepareCall(
client: HttpClient,
baseUrl: String,
request: Request<T>
): HttpClientCall? {
val preparedBody = prepareCallBody(client, baseUrl, request) ?: return null
return client.call {
url(
methodsCache[request.method()] ?: "$baseUrl/${request.method()}".also {
methodsCache[request.method()] = it
}
)
method = HttpMethod.Post
accept(ContentType.Application.Json)
body = preparedBody
build()
}
}
protected abstract fun <T : Any> prepareCallBody(
client: HttpClient,
baseUrl: String,
request: Request<T>
): Any?
}

View File

@ -1,48 +1,37 @@
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorCallFactory
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.* import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapWithCommonValues import com.github.insanusmokrassar.TelegramBotAPI.utils.mapWithCommonValues
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.HttpClientCall
import io.ktor.client.call.call
import io.ktor.client.request.accept
import io.ktor.client.request.forms.MultiPartFormDataContent import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData import io.ktor.client.request.forms.formData
import io.ktor.client.request.url
import io.ktor.http.* import io.ktor.http.*
class MultipartRequestCallFactory : KtorCallFactory { class MultipartRequestCallFactory : AbstractRequestCallFactory() {
override suspend fun <T: Any> prepareCall(
override fun <T : Any> prepareCallBody(
client: HttpClient, client: HttpClient,
baseUrl: String, baseUrl: String,
request: Request<T> request: Request<T>
): HttpClientCall? = (request as? MultipartRequest) ?.let { ): Any? = (request as? MultipartRequest) ?.let { castedRequest ->
castedRequest -> MultiPartFormDataContent(
client.call { formData {
url("$baseUrl/${castedRequest.method()}") val params = castedRequest.paramsJson.mapWithCommonValues()
method = HttpMethod.Post for ((key, value) in castedRequest.mediaMap + params) {
accept(ContentType.Application.Json) when (value) {
body = MultiPartFormDataContent( is MultipartFile -> append(
formData { key,
val params = castedRequest.paramsJson.mapWithCommonValues() value.file.asInput(),
for ((key, value) in castedRequest.mediaMap + params) { Headers.build {
when (value) { append(HttpHeaders.ContentType, value.mimeType)
is MultipartFile -> append( append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
key, }
value.file.asInput(), )
Headers.build { is FileId -> append(key, value.fileId)
append(HttpHeaders.ContentType, value.mimeType) else -> append(key, value.toString())
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
}
)
is FileId -> append(key, value.fileId)
else -> append(key, value.toString())
}
} }
} }
) }
build() )
}
} }
} }

View File

@ -1,36 +1,23 @@
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorCallFactory
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.* import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.HttpClientCall
import io.ktor.client.call.call
import io.ktor.client.request.accept
import io.ktor.client.request.url
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.HttpMethod
import io.ktor.http.content.TextContent import io.ktor.http.content.TextContent
class SimpleRequestCallFactory : KtorCallFactory { class SimpleRequestCallFactory : AbstractRequestCallFactory() {
override suspend fun <T: Any> prepareCall( override fun <T : Any> prepareCallBody(
client: HttpClient, client: HttpClient,
baseUrl: String, baseUrl: String,
request: Request<T> request: Request<T>
): HttpClientCall? = (request as? SimpleRequest<T>) ?.let { ): Any? = (request as? SimpleRequest<T>) ?.let { _ ->
castedRequest -> val content = request.toJsonWithoutNulls(SimpleRequestSerializer).toString()
client.call {
url("$baseUrl/${castedRequest.method()}")
method = HttpMethod.Post
accept(ContentType.Application.Json)
val content = request.toJsonWithoutNulls(SimpleRequestSerializer).toString() TextContent(
content,
body = TextContent( ContentType.Application.Json
content, )
ContentType.Application.Json
)
build()
}
} }
} }