From 4cc4d3d4ec19b6e2276c9cea89a1935641d692f0 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 31 Aug 2020 00:29:34 +0600 Subject: [PATCH 1/4] commonize url query parameters encoding/decoding --- .../ktor/client/StandardHttpClientGetPost.kt | 8 +++-- .../postssystem/ktor/HexConversations.kt | 6 ---- .../ktor/server/ServerRoutingShortcuts.kt | 35 +++++++++++-------- .../client/crud/KtorReadStandardCrudRepo.kt | 5 +-- .../server/crud/KtorReadStandardCrudRepo.kt | 4 +-- ...onfigureOneToManyReadKeyValueRepoRoutes.kt | 20 +++++------ 6 files changed, 41 insertions(+), 37 deletions(-) delete mode 100644 ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/HexConversations.kt diff --git a/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/client/StandardHttpClientGetPost.kt b/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/client/StandardHttpClientGetPost.kt index 77e38e75..2fbb2133 100644 --- a/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/client/StandardHttpClientGetPost.kt +++ b/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/client/StandardHttpClientGetPost.kt @@ -4,8 +4,7 @@ import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat import io.ktor.client.HttpClient import io.ktor.client.request.get import io.ktor.client.request.post -import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.* typealias BodyPair = Pair, T> @@ -18,6 +17,11 @@ suspend fun HttpClient.uniget( standardKtorSerialFormat.decodeFromByteArray(resultDeserializer, it) } +fun SerializationStrategy.encodeUrlQueryValue(value: T) = standardKtorSerialFormat.encodeToHexString( + this, + value +) + suspend fun HttpClient.unipost( url: String, bodyInfo: BodyPair, diff --git a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/HexConversations.kt b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/HexConversations.kt deleted file mode 100644 index eb7cb1d3..00000000 --- a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/HexConversations.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.insanusmokrassar.postssystem.ktor - -import kotlinx.serialization.* - -fun T.toHex(with: SerializationStrategy) = standardKtorSerialFormat.encodeToHexString(with, this) -fun String.fromHex(with: DeserializationStrategy): T = standardKtorSerialFormat.decodeFromHexString(with, this) diff --git a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt index 78336b61..7aacd5af 100644 --- a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt +++ b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt @@ -1,14 +1,12 @@ package com.insanusmokrassar.postssystem.ktor.server -import com.insanusmokrassar.postssystem.ktor.fromHex import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat import io.ktor.application.ApplicationCall import io.ktor.http.HttpStatusCode import io.ktor.response.respond import io.ktor.response.respondBytes import io.ktor.util.toByteArray -import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.* suspend fun ApplicationCall.unianswer( answerSerializer: SerializationStrategy, @@ -27,18 +25,6 @@ suspend fun ApplicationCall.uniload( request.receiveChannel().toByteArray() ) -fun ApplicationCall.uniloadFromQuery( - parameterName: String, - deserializer: DeserializationStrategy -): T? = getQueryParameter(parameterName) ?.fromHex(deserializer) - -suspend fun ApplicationCall.uniloadFromQueryOrSendError( - parameterName: String, - deserializer: DeserializationStrategy -): T? = uniloadFromQuery(parameterName, deserializer) ?: null.also { - respond(HttpStatusCode.BadRequest, "Request query parameters must contains $parameterName") -} - suspend fun ApplicationCall.getParameterOrSendError( field: String ) = parameters[field].also { @@ -58,3 +44,22 @@ suspend fun ApplicationCall.getQueryParameterOrSendError( respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field") } } + +fun ApplicationCall.decodeUrlQueryValue( + field: String, + deserializer: DeserializationStrategy +) = getQueryParameter(field) ?.let { + standardKtorSerialFormat.decodeFromHexString( + deserializer, + it + ) +} + +fun ApplicationCall.decodeUrlQueryValueOrSendError( + field: String, + deserializer: DeserializationStrategy +) = decodeUrlQueryValue(field, deserializer).also { + if (it == null) { + respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field") + } +} diff --git a/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/crud/KtorReadStandardCrudRepo.kt b/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/crud/KtorReadStandardCrudRepo.kt index 511dd3a2..65be8c49 100644 --- a/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/crud/KtorReadStandardCrudRepo.kt +++ b/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/crud/KtorReadStandardCrudRepo.kt @@ -1,6 +1,7 @@ package com.insanusmokrassar.postssystem.utils.repos.ktor.client.crud import com.insanusmokrassar.postssystem.ktor.* +import com.insanusmokrassar.postssystem.ktor.client.encodeUrlQueryValue import com.insanusmokrassar.postssystem.ktor.client.uniget import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult @@ -29,7 +30,7 @@ class KtorReadStandardCrudRepo ( baseUrl, getByIdRouting, mapOf( - "id" to id.toHex(idsSerializer) + "id" to idsSerializer.encodeUrlQueryValue(id) ) ), objectsSerializerNullable @@ -40,7 +41,7 @@ class KtorReadStandardCrudRepo ( baseUrl, containsRouting, mapOf( - "id" to id.toHex(idsSerializer) + "id" to idsSerializer.encodeUrlQueryValue(id) ) ), Boolean.serializer() diff --git a/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/crud/KtorReadStandardCrudRepo.kt b/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/crud/KtorReadStandardCrudRepo.kt index bbdc19cc..6e20f166 100644 --- a/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/crud/KtorReadStandardCrudRepo.kt +++ b/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/crud/KtorReadStandardCrudRepo.kt @@ -28,7 +28,7 @@ fun Route.configureReadStandardCrudRepoRoutes( } get(getByIdRouting) { - val id = call.uniloadFromQueryOrSendError( + val id = call.decodeUrlQueryValueOrSendError( "id", idsSerializer ) ?: return@get @@ -40,7 +40,7 @@ fun Route.configureReadStandardCrudRepoRoutes( } get(containsRouting) { - val id = call.uniloadFromQueryOrSendError( + val id = call.decodeUrlQueryValueOrSendError( "id", idsSerializer ) ?: return@get diff --git a/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/one_to_many/ConfigureOneToManyReadKeyValueRepoRoutes.kt b/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/one_to_many/ConfigureOneToManyReadKeyValueRepoRoutes.kt index 5f402ca7..1a48c7f8 100644 --- a/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/one_to_many/ConfigureOneToManyReadKeyValueRepoRoutes.kt +++ b/utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/one_to_many/ConfigureOneToManyReadKeyValueRepoRoutes.kt @@ -22,11 +22,11 @@ fun Route.configureOneToManyReadKeyValueRepoRoutes( get(getRoute) { val pagination = call.request.queryParameters.extractPagination - val key = call.uniloadFromQueryOrSendError( + val key = call.decodeUrlQueryValueOrSendError( keyParameterName, keySerializer ) ?: return@get - val reversed = call.uniloadFromQuery( + val reversed = call.decodeUrlQueryValue( reversedParameterName, Boolean.serializer() ) ?: false @@ -39,7 +39,7 @@ fun Route.configureOneToManyReadKeyValueRepoRoutes( get(keysRoute) { val pagination = call.request.queryParameters.extractPagination - val reversed = call.uniloadFromQuery( + val reversed = call.decodeUrlQueryValue( reversedParameterName, Boolean.serializer() ) ?: false @@ -51,10 +51,10 @@ fun Route.configureOneToManyReadKeyValueRepoRoutes( } get(containsByKeyRoute) { - val key = standardKtorSerialFormat.decodeFromHexString( - keySerializer, - call.getQueryParameterOrSendError(keyParameterName) ?: return@get - ) + val key = call.decodeUrlQueryValueOrSendError( + keyParameterName, + keySerializer + ) ?: return@get call.unianswer( Boolean.serializer(), @@ -63,11 +63,11 @@ fun Route.configureOneToManyReadKeyValueRepoRoutes( } get(containsByKeyValueRoute) { - val key = call.uniloadFromQueryOrSendError( + val key = call.decodeUrlQueryValueOrSendError( keyParameterName, keySerializer ) ?: return@get - val value = call.uniloadFromQueryOrSendError( + val value = call.decodeUrlQueryValueOrSendError( valueParameterName, valueSealizer ) ?: return@get @@ -79,7 +79,7 @@ fun Route.configureOneToManyReadKeyValueRepoRoutes( } get(countByKeyRoute) { - val key = call.uniloadFromQueryOrSendError( + val key = call.decodeUrlQueryValueOrSendError( keyParameterName, keySerializer ) ?: return@get From 617ac31ca11e15312bff1a4f3c3c7198bd45fc22 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 31 Aug 2020 00:40:58 +0600 Subject: [PATCH 2/4] hotfix --- .../ktor/server/ServerRoutingShortcuts.kt | 2 +- .../one_to_many/KtorOneToManyReadKeyValueRepo.kt | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt index 7aacd5af..88bae92b 100644 --- a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt +++ b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/ServerRoutingShortcuts.kt @@ -55,7 +55,7 @@ fun ApplicationCall.decodeUrlQueryValue( ) } -fun ApplicationCall.decodeUrlQueryValueOrSendError( +suspend fun ApplicationCall.decodeUrlQueryValueOrSendError( field: String, deserializer: DeserializationStrategy ) = decodeUrlQueryValue(field, deserializer).also { diff --git a/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/one_to_many/KtorOneToManyReadKeyValueRepo.kt b/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/one_to_many/KtorOneToManyReadKeyValueRepo.kt index 0df572fa..e0736e40 100644 --- a/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/one_to_many/KtorOneToManyReadKeyValueRepo.kt +++ b/utils/repos/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/client/one_to_many/KtorOneToManyReadKeyValueRepo.kt @@ -1,6 +1,7 @@ package com.insanusmokrassar.postssystem.utils.repos.ktor.client.one_to_many import com.insanusmokrassar.postssystem.ktor.* +import com.insanusmokrassar.postssystem.ktor.client.encodeUrlQueryValue import com.insanusmokrassar.postssystem.ktor.client.uniget import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult @@ -24,8 +25,8 @@ class KtorOneToManyReadKeyValueRepo ( baseUrl, getRoute, mapOf( - keyParameterName to k.toHex(keySerializer), - reversedParameterName to reversed.toHex(Boolean.serializer()) + keyParameterName to keySerializer.encodeUrlQueryValue(k), + reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed) ) + pagination.asUrlQueryParts ), paginationValueResultSerializer @@ -36,7 +37,7 @@ class KtorOneToManyReadKeyValueRepo ( baseUrl, keysRoute, mapOf( - reversedParameterName to reversed.toHex(Boolean.serializer()) + reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed) ) + pagination.asUrlQueryParts ), paginationKeyResultSerializer @@ -46,7 +47,7 @@ class KtorOneToManyReadKeyValueRepo ( buildStandardUrl( baseUrl, containsByKeyRoute, - mapOf(keyParameterName to k.toHex(keySerializer)) + mapOf(keyParameterName to keySerializer.encodeUrlQueryValue(k)) ), Boolean.serializer() ) @@ -56,8 +57,8 @@ class KtorOneToManyReadKeyValueRepo ( baseUrl, containsByKeyValueRoute, mapOf( - keyParameterName to k.toHex(keySerializer), - valueParameterName to v.toHex(valueSerializer), + keyParameterName to keySerializer.encodeUrlQueryValue(k), + valueParameterName to valueSerializer.encodeUrlQueryValue(v), ) ), Boolean.serializer() @@ -68,7 +69,7 @@ class KtorOneToManyReadKeyValueRepo ( baseUrl, countByKeyRoute, mapOf( - keyParameterName to k.toHex(keySerializer) + keyParameterName to keySerializer.encodeUrlQueryValue(k) ) ), Long.serializer() From 9a5585957fa12575a468b22d6ade706a62eeb6ff Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 31 Aug 2020 00:46:53 +0600 Subject: [PATCH 3/4] update tools for urls --- .../postssystem/ktor/BuildStandardUrl.kt | 14 ++++++++++++++ .../postssystem/ktor/QueryParamsBuilder.kt | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/BuildStandardUrl.kt b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/BuildStandardUrl.kt index 1204ec93..22be8bcc 100644 --- a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/BuildStandardUrl.kt +++ b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/BuildStandardUrl.kt @@ -7,3 +7,17 @@ fun buildStandardUrl( ) = "$basePart/$subpart".includeQueryParams( parameters ) + +fun buildStandardUrl( + basePart: String, + subpart: String, + parameters: List +) = "$basePart/$subpart".includeQueryParams( + parameters +) + +fun buildStandardUrl( + basePart: String, + subpart: String, + vararg parameters: QueryParam +) = buildStandardUrl(basePart, subpart, parameters.toList()) diff --git a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/QueryParamsBuilder.kt b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/QueryParamsBuilder.kt index 00210808..1d50ef62 100644 --- a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/QueryParamsBuilder.kt +++ b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/QueryParamsBuilder.kt @@ -1,13 +1,22 @@ package com.insanusmokrassar.postssystem.ktor +typealias QueryParam = Pair typealias QueryParams = Map val QueryParams.asUrlQuery: String get() = keys.joinToString("&") { "${it}${get(it) ?.let { value -> "=$value" }}" } + +val List.asUrlQuery: String + get() = joinToString("&") { (key, value) -> "${key}${value ?.let { _ -> "=$value" }}" } + fun String.includeQueryParams( queryParams: QueryParams ): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}" +fun String.includeQueryParams( + queryParams: List +): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}" + val String.parseUrlQuery: QueryParams get() = split("&").map { it.split("=").let { pair -> From 14e0196c11320883a6c093f64292177b3a35e9a7 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 31 Aug 2020 00:51:48 +0600 Subject: [PATCH 4/4] update tools for urls --- .../insanusmokrassar/postssystem/ktor/PaginationInUrl.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/PaginationInUrl.kt b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/PaginationInUrl.kt index fe957a2a..60cb0244 100644 --- a/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/PaginationInUrl.kt +++ b/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/PaginationInUrl.kt @@ -12,6 +12,12 @@ val Pagination.asUrlQueryParts "size" to size.toString() ) +val Pagination.asUrlQueryArrayParts + get() = arrayOf( + "page" to page.toString(), + "size" to size.toString() + ) + val Map.extractPagination: Pagination get() = SimplePagination( get("page") ?.toIntOrNull() ?: 0,