Feature/update kotlin dependecies template (#12966)

* update Kotlin & Ktor versions

* update samples

* fix gradle version

* update the ktor client templates and project samples

* update the ktor client templates and project samples

* revert multiplatform upgrade

* update kotlin multiplatform

* upload kotlin Multiplatform samples

* fix gson ktor sample

* update samples

* fix: unused imports

* fix imports of ApiClient

* update kotlin samples
This commit is contained in:
mm's
2022-09-04 17:27:24 +02:00
committed by GitHub
parent f6be1d07bc
commit ef6d383433
68 changed files with 466 additions and 587 deletions

View File

@@ -8,10 +8,10 @@ plugins {
group = "org.openapitools"
version = "1.0.0"
val kotlin_version = "1.6.0"
val coroutines_version = "1.5.2"
val serialization_version = "1.3.0"
val ktor_version = "1.6.4"
val kotlin_version = "1.6.10"
val coroutines_version = "1.6.3"
val serialization_version = "1.3.3"
val ktor_version = "2.0.3"
repositories {
mavenCentral()
@@ -30,9 +30,11 @@ kotlin {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version")
api("io.ktor:ktor-client-core:$ktor_version")
api("io.ktor:ktor-client-json:$ktor_version")
api("io.ktor:ktor-client-serialization:$ktor_version")
api("io.ktor:ktor-client-content-negotiation:$ktor_version")
api("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
}
}

View File

@@ -25,7 +25,6 @@ import org.openapitools.client.infrastructure.*
import io.ktor.client.HttpClientConfig
import io.ktor.client.request.forms.formData
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.features.json.serializer.KotlinxSerializer
import kotlinx.serialization.json.Json
import io.ktor.http.ParametersBuilder
import kotlinx.serialization.*

View File

@@ -3,43 +3,31 @@ package org.openapitools.client.infrastructure
import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.JsonSerializer
import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.serialization.kotlinx.json.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.FormDataContent
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.header
import io.ktor.client.request.parameter
import io.ktor.client.statement.HttpResponse
import io.ktor.client.utils.EmptyContent
import io.ktor.http.*
import io.ktor.http.content.OutgoingContent
import io.ktor.http.content.PartData
import kotlin.Unit
import kotlinx.serialization.json.Json
import org.openapitools.client.apis.*
import org.openapitools.client.models.*
import org.openapitools.client.auth.*
open class ApiClient(
private val baseUrl: String,
httpClientEngine: HttpClientEngine?,
httpClientConfig: ((HttpClientConfig<*>) -> Unit)? = null,
private val json: Json
private val jsonBlock: Json
) {
private val serializer: JsonSerializer by lazy {
KotlinxSerializer(json).ignoreOutgoingContent()
}
private val clientConfig: (HttpClientConfig<*>) -> Unit by lazy {
{
// Hold a reference to the serializer to avoid freezing the entire ApiClient instance
// when the JsonFeature is configured.
val serializerReference = serializer
it.install(JsonFeature) { serializer = serializerReference }
it.install(ContentNegotiation) { json(jsonBlock) }
httpClientConfig?.invoke(it)
}
}
@@ -52,7 +40,11 @@ open class ApiClient(
companion object {
const val BASE_URL = "http://localhost"
val JSON_DEFAULT = Json { ignoreUnknownKeys = true }
val JSON_DEFAULT = Json {
ignoreUnknownKeys = true
prettyPrint = true
isLenient = true
}
protected val UNSAFE_HEADERS = listOf(HttpHeaders.ContentType)
}
@@ -132,18 +124,13 @@ open class ApiClient(
return request(requestConfig, FormDataContent(body ?: Parameters.Empty), authNames)
}
protected suspend fun <T: Any?> jsonRequest(requestConfig: RequestConfig<T>, body: Any? = null, authNames: kotlin.collections.List<String>): HttpResponse {
val contentType = (requestConfig.headers[HttpHeaders.ContentType]?.let { ContentType.parse(it) }
?: ContentType.Application.Json)
return if (body != null) request(requestConfig, serializer.write(body, contentType), authNames)
else request(requestConfig, authNames = authNames)
}
protected suspend fun <T: Any?> jsonRequest(requestConfig: RequestConfig<T>, body: Any? = null, authNames: kotlin.collections.List<String>): HttpResponse = request(requestConfig, body, authNames)
protected suspend fun <T: Any?> request(requestConfig: RequestConfig<T>, body: OutgoingContent = EmptyContent, authNames: kotlin.collections.List<String>): HttpResponse {
protected suspend fun <T: Any?> request(requestConfig: RequestConfig<T>, body: Any? = null, authNames: kotlin.collections.List<String>): HttpResponse {
requestConfig.updateForAuth<T>(authNames)
val headers = requestConfig.headers
return client.request<HttpResponse> {
return client.request {
this.url {
this.takeFrom(URLBuilder(baseUrl))
appendPath(requestConfig.path.trimStart('/').split('/'))
@@ -156,7 +143,7 @@ open class ApiClient(
this.method = requestConfig.method.httpMethod
headers.filter { header -> !UNSAFE_HEADERS.contains(header.key) }.forEach { header -> this.header(header.key, header.value) }
if (requestConfig.method in listOf(RequestMethod.PUT, RequestMethod.POST, RequestMethod.PATCH))
this.body = body
this.setBody(body)
}
}
@@ -182,14 +169,4 @@ open class ApiClient(
RequestMethod.POST -> HttpMethod.Post
RequestMethod.OPTIONS -> HttpMethod.Options
}
}
// https://github.com/ktorio/ktor/issues/851
private fun JsonSerializer.ignoreOutgoingContent() = IgnoreOutgoingContentJsonSerializer(this)
private class IgnoreOutgoingContentJsonSerializer(private val delegate: JsonSerializer) : JsonSerializer by delegate {
override fun write(data: Any): OutgoingContent {
if (data is OutgoingContent) return data
return delegate.write(data)
}
}
}

View File

@@ -14,7 +14,7 @@ private fun ByteArray.clearFrom(from: Int) = (from until size).forEach { this[it
private fun Int.toBase64(): Char = BASE64_ALPHABET[this]
private fun Byte.fromBase64(): Byte = BASE64_INVERSE_ALPHABET[toInt() and 0xff].toByte() and BASE64_MASK
internal fun ByteArray.encodeBase64(): String = buildPacket { writeFully(this@encodeBase64) }.encodeBase64()
internal fun String.decodeBase64Bytes(): ByteArray = buildPacket { writeStringUtf8(dropLastWhile { it == BASE64_PAD }) }.decodeBase64Bytes().readBytes()
internal fun String.decodeBase64Bytes(): ByteArray = buildPacket { dropLastWhile { it == BASE64_PAD } }.decodeBase64Bytes().readBytes()
/**
* Encode [bytes] as a HEX string with no spaces, newlines and `0x` prefixes.

View File

@@ -1,9 +1,9 @@
package org.openapitools.client.infrastructure
import io.ktor.client.call.TypeInfo
import io.ktor.client.call.typeInfo
import io.ktor.http.Headers
import io.ktor.http.isSuccess
import io.ktor.util.reflect.TypeInfo
import io.ktor.util.reflect.typeInfo
open class HttpResponse<T : Any>(val response: io.ktor.client.statement.HttpResponse, val provider: BodyProvider<T>) {
val status: Int = response.status.value
@@ -29,11 +29,11 @@ interface BodyProvider<T : Any> {
class TypedBodyProvider<T : Any>(private val type: TypeInfo) : BodyProvider<T> {
@Suppress("UNCHECKED_CAST")
override suspend fun body(response: io.ktor.client.statement.HttpResponse): T =
response.call.receive(type) as T
response.call.body(type) as T
@Suppress("UNCHECKED_CAST")
override suspend fun <V : Any> typedBody(response: io.ktor.client.statement.HttpResponse, type: TypeInfo): V =
response.call.receive(type) as V
response.call.body(type) as V
}
class MappedBodyProvider<S : Any, T : Any>(private val provider: BodyProvider<S>, private val block: S.() -> T) : BodyProvider<T> {