Merge branch 'master' into key_value_impl
This commit is contained in:
commit
33bdd83e97
@ -4,8 +4,7 @@ import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
|||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import kotlinx.serialization.DeserializationStrategy
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.SerializationStrategy
|
|
||||||
|
|
||||||
typealias BodyPair<T> = Pair<SerializationStrategy<T>, T>
|
typealias BodyPair<T> = Pair<SerializationStrategy<T>, T>
|
||||||
|
|
||||||
@ -18,6 +17,11 @@ suspend fun <ResultType> HttpClient.uniget(
|
|||||||
standardKtorSerialFormat.decodeFromByteArray(resultDeserializer, it)
|
standardKtorSerialFormat.decodeFromByteArray(resultDeserializer, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> SerializationStrategy<T>.encodeUrlQueryValue(value: T) = standardKtorSerialFormat.encodeToHexString(
|
||||||
|
this,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun <BodyType, ResultType> HttpClient.unipost(
|
suspend fun <BodyType, ResultType> HttpClient.unipost(
|
||||||
url: String,
|
url: String,
|
||||||
bodyInfo: BodyPair<BodyType>,
|
bodyInfo: BodyPair<BodyType>,
|
||||||
|
@ -7,3 +7,17 @@ fun buildStandardUrl(
|
|||||||
) = "$basePart/$subpart".includeQueryParams(
|
) = "$basePart/$subpart".includeQueryParams(
|
||||||
parameters
|
parameters
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun buildStandardUrl(
|
||||||
|
basePart: String,
|
||||||
|
subpart: String,
|
||||||
|
parameters: List<QueryParam>
|
||||||
|
) = "$basePart/$subpart".includeQueryParams(
|
||||||
|
parameters
|
||||||
|
)
|
||||||
|
|
||||||
|
fun buildStandardUrl(
|
||||||
|
basePart: String,
|
||||||
|
subpart: String,
|
||||||
|
vararg parameters: QueryParam
|
||||||
|
) = buildStandardUrl(basePart, subpart, parameters.toList())
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package com.insanusmokrassar.postssystem.ktor
|
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
|
|
||||||
fun <T> T.toHex(with: SerializationStrategy<T>) = standardKtorSerialFormat.encodeToHexString(with, this)
|
|
||||||
fun <T> String.fromHex(with: DeserializationStrategy<T>): T = standardKtorSerialFormat.decodeFromHexString(with, this)
|
|
@ -12,6 +12,12 @@ val Pagination.asUrlQueryParts
|
|||||||
"size" to size.toString()
|
"size" to size.toString()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val Pagination.asUrlQueryArrayParts
|
||||||
|
get() = arrayOf(
|
||||||
|
"page" to page.toString(),
|
||||||
|
"size" to size.toString()
|
||||||
|
)
|
||||||
|
|
||||||
val Map<String, String?>.extractPagination: Pagination
|
val Map<String, String?>.extractPagination: Pagination
|
||||||
get() = SimplePagination(
|
get() = SimplePagination(
|
||||||
get("page") ?.toIntOrNull() ?: 0,
|
get("page") ?.toIntOrNull() ?: 0,
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
package com.insanusmokrassar.postssystem.ktor
|
package com.insanusmokrassar.postssystem.ktor
|
||||||
|
|
||||||
|
typealias QueryParam = Pair<String, String?>
|
||||||
typealias QueryParams = Map<String, String?>
|
typealias QueryParams = Map<String, String?>
|
||||||
|
|
||||||
val QueryParams.asUrlQuery: String
|
val QueryParams.asUrlQuery: String
|
||||||
get() = keys.joinToString("&") { "${it}${get(it) ?.let { value -> "=$value" }}" }
|
get() = keys.joinToString("&") { "${it}${get(it) ?.let { value -> "=$value" }}" }
|
||||||
|
|
||||||
|
val List<QueryParam>.asUrlQuery: String
|
||||||
|
get() = joinToString("&") { (key, value) -> "${key}${value ?.let { _ -> "=$value" }}" }
|
||||||
|
|
||||||
fun String.includeQueryParams(
|
fun String.includeQueryParams(
|
||||||
queryParams: QueryParams
|
queryParams: QueryParams
|
||||||
): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}"
|
): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}"
|
||||||
|
|
||||||
|
fun String.includeQueryParams(
|
||||||
|
queryParams: List<QueryParam>
|
||||||
|
): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}"
|
||||||
|
|
||||||
val String.parseUrlQuery: QueryParams
|
val String.parseUrlQuery: QueryParams
|
||||||
get() = split("&").map {
|
get() = split("&").map {
|
||||||
it.split("=").let { pair ->
|
it.split("=").let { pair ->
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package com.insanusmokrassar.postssystem.ktor.server
|
package com.insanusmokrassar.postssystem.ktor.server
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.ktor.fromHex
|
|
||||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||||
import io.ktor.application.ApplicationCall
|
import io.ktor.application.ApplicationCall
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.response.respondBytes
|
import io.ktor.response.respondBytes
|
||||||
import io.ktor.util.toByteArray
|
import io.ktor.util.toByteArray
|
||||||
import kotlinx.serialization.DeserializationStrategy
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.SerializationStrategy
|
|
||||||
|
|
||||||
suspend fun <T> ApplicationCall.unianswer(
|
suspend fun <T> ApplicationCall.unianswer(
|
||||||
answerSerializer: SerializationStrategy<T>,
|
answerSerializer: SerializationStrategy<T>,
|
||||||
@ -27,18 +25,6 @@ suspend fun <T> ApplicationCall.uniload(
|
|||||||
request.receiveChannel().toByteArray()
|
request.receiveChannel().toByteArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <T> ApplicationCall.uniloadFromQuery(
|
|
||||||
parameterName: String,
|
|
||||||
deserializer: DeserializationStrategy<T>
|
|
||||||
): T? = getQueryParameter(parameterName) ?.fromHex(deserializer)
|
|
||||||
|
|
||||||
suspend fun <T> ApplicationCall.uniloadFromQueryOrSendError(
|
|
||||||
parameterName: String,
|
|
||||||
deserializer: DeserializationStrategy<T>
|
|
||||||
): T? = uniloadFromQuery(parameterName, deserializer) ?: null.also {
|
|
||||||
respond(HttpStatusCode.BadRequest, "Request query parameters must contains $parameterName")
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun ApplicationCall.getParameterOrSendError(
|
suspend fun ApplicationCall.getParameterOrSendError(
|
||||||
field: String
|
field: String
|
||||||
) = parameters[field].also {
|
) = parameters[field].also {
|
||||||
@ -58,3 +44,22 @@ suspend fun ApplicationCall.getQueryParameterOrSendError(
|
|||||||
respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
|
respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> ApplicationCall.decodeUrlQueryValue(
|
||||||
|
field: String,
|
||||||
|
deserializer: DeserializationStrategy<T>
|
||||||
|
) = getQueryParameter(field) ?.let {
|
||||||
|
standardKtorSerialFormat.decodeFromHexString(
|
||||||
|
deserializer,
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> ApplicationCall.decodeUrlQueryValueOrSendError(
|
||||||
|
field: String,
|
||||||
|
deserializer: DeserializationStrategy<T>
|
||||||
|
) = decodeUrlQueryValue(field, deserializer).also {
|
||||||
|
if (it == null) {
|
||||||
|
respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.crud
|
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.crud
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.ktor.*
|
import com.insanusmokrassar.postssystem.ktor.*
|
||||||
|
import com.insanusmokrassar.postssystem.ktor.client.encodeUrlQueryValue
|
||||||
import com.insanusmokrassar.postssystem.ktor.client.uniget
|
import com.insanusmokrassar.postssystem.ktor.client.uniget
|
||||||
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
@ -29,7 +30,7 @@ class KtorReadStandardCrudRepo<ObjectType, IdType> (
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
getByIdRouting,
|
getByIdRouting,
|
||||||
mapOf(
|
mapOf(
|
||||||
"id" to id.toHex(idsSerializer)
|
"id" to idsSerializer.encodeUrlQueryValue(id)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
objectsSerializerNullable
|
objectsSerializerNullable
|
||||||
@ -40,7 +41,7 @@ class KtorReadStandardCrudRepo<ObjectType, IdType> (
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
containsRouting,
|
containsRouting,
|
||||||
mapOf(
|
mapOf(
|
||||||
"id" to id.toHex(idsSerializer)
|
"id" to idsSerializer.encodeUrlQueryValue(id)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Boolean.serializer()
|
Boolean.serializer()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.one_to_many
|
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.ktor.*
|
import com.insanusmokrassar.postssystem.ktor.*
|
||||||
|
import com.insanusmokrassar.postssystem.ktor.client.encodeUrlQueryValue
|
||||||
import com.insanusmokrassar.postssystem.ktor.client.uniget
|
import com.insanusmokrassar.postssystem.ktor.client.uniget
|
||||||
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
@ -24,8 +25,8 @@ class KtorOneToManyReadKeyValueRepo<Key, Value> (
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
getRoute,
|
getRoute,
|
||||||
mapOf(
|
mapOf(
|
||||||
keyParameterName to k.toHex(keySerializer),
|
keyParameterName to keySerializer.encodeUrlQueryValue(k),
|
||||||
reversedParameterName to reversed.toHex(Boolean.serializer())
|
reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed)
|
||||||
) + pagination.asUrlQueryParts
|
) + pagination.asUrlQueryParts
|
||||||
),
|
),
|
||||||
paginationValueResultSerializer
|
paginationValueResultSerializer
|
||||||
@ -36,7 +37,7 @@ class KtorOneToManyReadKeyValueRepo<Key, Value> (
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
keysRoute,
|
keysRoute,
|
||||||
mapOf(
|
mapOf(
|
||||||
reversedParameterName to reversed.toHex(Boolean.serializer())
|
reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed)
|
||||||
) + pagination.asUrlQueryParts
|
) + pagination.asUrlQueryParts
|
||||||
),
|
),
|
||||||
paginationKeyResultSerializer
|
paginationKeyResultSerializer
|
||||||
@ -46,7 +47,7 @@ class KtorOneToManyReadKeyValueRepo<Key, Value> (
|
|||||||
buildStandardUrl(
|
buildStandardUrl(
|
||||||
baseUrl,
|
baseUrl,
|
||||||
containsByKeyRoute,
|
containsByKeyRoute,
|
||||||
mapOf(keyParameterName to k.toHex(keySerializer))
|
mapOf(keyParameterName to keySerializer.encodeUrlQueryValue(k))
|
||||||
),
|
),
|
||||||
Boolean.serializer()
|
Boolean.serializer()
|
||||||
)
|
)
|
||||||
@ -56,8 +57,8 @@ class KtorOneToManyReadKeyValueRepo<Key, Value> (
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
containsByKeyValueRoute,
|
containsByKeyValueRoute,
|
||||||
mapOf(
|
mapOf(
|
||||||
keyParameterName to k.toHex(keySerializer),
|
keyParameterName to keySerializer.encodeUrlQueryValue(k),
|
||||||
valueParameterName to v.toHex(valueSerializer),
|
valueParameterName to valueSerializer.encodeUrlQueryValue(v),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Boolean.serializer()
|
Boolean.serializer()
|
||||||
@ -68,7 +69,7 @@ class KtorOneToManyReadKeyValueRepo<Key, Value> (
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
countByKeyRoute,
|
countByKeyRoute,
|
||||||
mapOf(
|
mapOf(
|
||||||
keyParameterName to k.toHex(keySerializer)
|
keyParameterName to keySerializer.encodeUrlQueryValue(k)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Long.serializer()
|
Long.serializer()
|
||||||
|
@ -28,7 +28,7 @@ fun <ObjectType, IdType> Route.configureReadStandardCrudRepoRoutes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(getByIdRouting) {
|
get(getByIdRouting) {
|
||||||
val id = call.uniloadFromQueryOrSendError(
|
val id = call.decodeUrlQueryValueOrSendError(
|
||||||
"id",
|
"id",
|
||||||
idsSerializer
|
idsSerializer
|
||||||
) ?: return@get
|
) ?: return@get
|
||||||
@ -40,7 +40,7 @@ fun <ObjectType, IdType> Route.configureReadStandardCrudRepoRoutes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(containsRouting) {
|
get(containsRouting) {
|
||||||
val id = call.uniloadFromQueryOrSendError(
|
val id = call.decodeUrlQueryValueOrSendError(
|
||||||
"id",
|
"id",
|
||||||
idsSerializer
|
idsSerializer
|
||||||
) ?: return@get
|
) ?: return@get
|
||||||
|
@ -22,11 +22,11 @@ fun <Key, Value> Route.configureOneToManyReadKeyValueRepoRoutes(
|
|||||||
|
|
||||||
get(getRoute) {
|
get(getRoute) {
|
||||||
val pagination = call.request.queryParameters.extractPagination
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
val key = call.uniloadFromQueryOrSendError(
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
keyParameterName,
|
keyParameterName,
|
||||||
keySerializer
|
keySerializer
|
||||||
) ?: return@get
|
) ?: return@get
|
||||||
val reversed = call.uniloadFromQuery(
|
val reversed = call.decodeUrlQueryValue(
|
||||||
reversedParameterName,
|
reversedParameterName,
|
||||||
Boolean.serializer()
|
Boolean.serializer()
|
||||||
) ?: false
|
) ?: false
|
||||||
@ -39,7 +39,7 @@ fun <Key, Value> Route.configureOneToManyReadKeyValueRepoRoutes(
|
|||||||
|
|
||||||
get(keysRoute) {
|
get(keysRoute) {
|
||||||
val pagination = call.request.queryParameters.extractPagination
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
val reversed = call.uniloadFromQuery(
|
val reversed = call.decodeUrlQueryValue(
|
||||||
reversedParameterName,
|
reversedParameterName,
|
||||||
Boolean.serializer()
|
Boolean.serializer()
|
||||||
) ?: false
|
) ?: false
|
||||||
@ -51,10 +51,10 @@ fun <Key, Value> Route.configureOneToManyReadKeyValueRepoRoutes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(containsByKeyRoute) {
|
get(containsByKeyRoute) {
|
||||||
val key = standardKtorSerialFormat.decodeFromHexString(
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
keySerializer,
|
keyParameterName,
|
||||||
call.getQueryParameterOrSendError(keyParameterName) ?: return@get
|
keySerializer
|
||||||
)
|
) ?: return@get
|
||||||
|
|
||||||
call.unianswer(
|
call.unianswer(
|
||||||
Boolean.serializer(),
|
Boolean.serializer(),
|
||||||
@ -63,11 +63,11 @@ fun <Key, Value> Route.configureOneToManyReadKeyValueRepoRoutes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(containsByKeyValueRoute) {
|
get(containsByKeyValueRoute) {
|
||||||
val key = call.uniloadFromQueryOrSendError(
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
keyParameterName,
|
keyParameterName,
|
||||||
keySerializer
|
keySerializer
|
||||||
) ?: return@get
|
) ?: return@get
|
||||||
val value = call.uniloadFromQueryOrSendError(
|
val value = call.decodeUrlQueryValueOrSendError(
|
||||||
valueParameterName,
|
valueParameterName,
|
||||||
valueSealizer
|
valueSealizer
|
||||||
) ?: return@get
|
) ?: return@get
|
||||||
@ -79,7 +79,7 @@ fun <Key, Value> Route.configureOneToManyReadKeyValueRepoRoutes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(countByKeyRoute) {
|
get(countByKeyRoute) {
|
||||||
val key = call.uniloadFromQueryOrSendError(
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
keyParameterName,
|
keyParameterName,
|
||||||
keySerializer
|
keySerializer
|
||||||
) ?: return@get
|
) ?: return@get
|
||||||
|
Loading…
Reference in New Issue
Block a user