From 93bd094823cb1808eb35ecd6a71f518031b6c158 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 14 Aug 2020 12:06:37 +0600 Subject: [PATCH] add server realization of post repos --- .../core/content/api/ReadContentRepo.kt | 2 +- .../core/exposed/ExposedContentRepo.kt | 2 +- .../client/content/ContentRepoKtorClient.kt | 33 ++++++---- .../content/ReadContentRepoKtorClient.kt | 2 +- .../postssystem/core/ktor/ContentRoutes.kt | 2 + .../content/ContentRepoRoutingConfigurator.kt | 26 ++++++++ .../ReadContentRepoRoutingConfigurator.kt | 55 ++++++++++++++++ .../WriteContentRepoRoutingConfigurator.kt | 63 +++++++++++++++++++ .../ktor/server/PaginationInUrl.kt | 10 +++ .../ApplicationRoutingConfigurator.kt | 3 +- .../standardKtorSerialFormatContentType.kt | 5 ++ 11 files changed, 187 insertions(+), 16 deletions(-) create mode 100644 core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ContentRepoRoutingConfigurator.kt create mode 100644 core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ReadContentRepoRoutingConfigurator.kt create mode 100644 core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/WriteContentRepoRoutingConfigurator.kt create mode 100644 ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/PaginationInUrl.kt create mode 100644 ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/standardKtorSerialFormatContentType.kt diff --git a/core/api/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/content/api/ReadContentRepo.kt b/core/api/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/content/api/ReadContentRepo.kt index d17e3817..cbca2611 100644 --- a/core/api/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/content/api/ReadContentRepo.kt +++ b/core/api/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/content/api/ReadContentRepo.kt @@ -21,5 +21,5 @@ interface ReadContentRepo { /** * @return all [RegisteredContent] by pages basing on their creation date */ - suspend fun getContentByPagination(pagination: Pagination): PaginationResult + suspend fun getContentByPagination(pagination: Pagination): PaginationResult } \ No newline at end of file diff --git a/core/exposed/src/main/kotlin/com/insanusmokrassar/postssystem/core/exposed/ExposedContentRepo.kt b/core/exposed/src/main/kotlin/com/insanusmokrassar/postssystem/core/exposed/ExposedContentRepo.kt index e941308a..343093b0 100644 --- a/core/exposed/src/main/kotlin/com/insanusmokrassar/postssystem/core/exposed/ExposedContentRepo.kt +++ b/core/exposed/src/main/kotlin/com/insanusmokrassar/postssystem/core/exposed/ExposedContentRepo.kt @@ -131,7 +131,7 @@ private class ContentRepoDatabaseTable( select { idColumn.eq(id) }.limit(1).firstOrNull() ?.asRegisteredContent(content) } } - override suspend fun getContentByPagination(pagination: Pagination): PaginationResult { + override suspend fun getContentByPagination(pagination: Pagination): PaginationResult { return transaction( db = database ) { diff --git a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ContentRepoKtorClient.kt b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ContentRepoKtorClient.kt index b644855b..f1498a92 100644 --- a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ContentRepoKtorClient.kt +++ b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ContentRepoKtorClient.kt @@ -1,18 +1,27 @@ package com.insanusmokrassar.postssystem.core.ktor.client.content import com.insanusmokrassar.postssystem.core.content.api.* +import com.insanusmokrassar.postssystem.core.ktor.contentRootRoute import io.ktor.client.HttpClient import io.ktor.client.features.websocket.WebSockets -class ContentRepoKtorClient( - baseUrl: String, - client: HttpClient = HttpClient { - install(WebSockets) - } -) : ContentRepo, ReadContentRepo by ReadContentRepoKtorClient( - baseUrl, - client -), WriteContentRepo by WriteContentRepoKtorClient( - baseUrl, - client -) +class ContentRepoKtorClient private constructor( + readContentRepo: ReadContentRepo, + writeContentRepo: WriteContentRepo +) : ContentRepo, ReadContentRepo by readContentRepo, WriteContentRepo by writeContentRepo { + constructor( + baseUrl: String, + client: HttpClient = HttpClient { + install(WebSockets) + } + ) : this( + ReadContentRepoKtorClient( + "$baseUrl/$contentRootRoute", + client + ), + WriteContentRepoKtorClient( + "$baseUrl/$contentRootRoute", + client + ) + ) +} diff --git a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ReadContentRepoKtorClient.kt b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ReadContentRepoKtorClient.kt index e9250fc4..568824bd 100644 --- a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ReadContentRepoKtorClient.kt +++ b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/content/ReadContentRepoKtorClient.kt @@ -27,7 +27,7 @@ class ReadContentRepoKtorClient( standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it) } - override suspend fun getContentByPagination(pagination: Pagination): PaginationResult = client.get( + override suspend fun getContentByPagination(pagination: Pagination): PaginationResult = client.get( "$baseUrl/$getContentByPaginationRoute".includeQueryParams( pagination.asUrlQueryParts ) diff --git a/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/ContentRoutes.kt b/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/ContentRoutes.kt index f5ba141d..84c7452e 100644 --- a/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/ContentRoutes.kt +++ b/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/ContentRoutes.kt @@ -1,5 +1,7 @@ package com.insanusmokrassar.postssystem.core.ktor +const val contentRootRoute = "content" + const val getContentsIdsRoute = "getContentsIds" const val getContentByIdRoute = "getContentById" const val getContentByPaginationRoute = "getContentByPagination" diff --git a/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ContentRepoRoutingConfigurator.kt b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ContentRepoRoutingConfigurator.kt new file mode 100644 index 00000000..833cb6c0 --- /dev/null +++ b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ContentRepoRoutingConfigurator.kt @@ -0,0 +1,26 @@ +package com.insanusmokrassar.postssystem.core.ktor.server.content + +import com.insanusmokrassar.postssystem.core.content.api.ContentRepo +import com.insanusmokrassar.postssystem.core.ktor.contentRootRoute +import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator +import io.ktor.routing.Route +import io.ktor.routing.route + +fun Route.configureContentRepoRoutes( + proxyTo: ContentRepo +) { + route( + contentRootRoute + ) { + configureReadContentRepoRoutes(proxyTo) + configureWriteContentRepoRoutes(proxyTo) + } +} + +class ContentRepoRoutingConfigurator( + private val proxyTo: ContentRepo +) : ApplicationRoutingConfigurator.Element { + override fun Route.invoke() { + configureContentRepoRoutes(proxyTo) + } +} \ No newline at end of file diff --git a/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ReadContentRepoRoutingConfigurator.kt b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ReadContentRepoRoutingConfigurator.kt new file mode 100644 index 00000000..c46205de --- /dev/null +++ b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/ReadContentRepoRoutingConfigurator.kt @@ -0,0 +1,55 @@ +package com.insanusmokrassar.postssystem.core.ktor.server.content + +import com.insanusmokrassar.postssystem.core.content.RegisteredContent +import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo +import com.insanusmokrassar.postssystem.core.ktor.* +import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator +import com.insanusmokrassar.postssystem.ktor.server.extractPagination +import com.insanusmokrassar.postssystem.ktor.server.standardKtorSerialFormatContentType +import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat +import io.ktor.application.call +import io.ktor.http.HttpStatusCode +import io.ktor.response.respond +import io.ktor.response.respondBytes +import io.ktor.routing.* +import kotlinx.serialization.builtins.nullable + +fun Route.configureReadContentRepoRoutes( + proxyTo: ReadContentRepo +) { + get(getContentsIdsRoute) { + call.respondBytes( + standardKtorSerialFormat.dump(contentIdsSerializer, proxyTo.getContentsIds()), + standardKtorSerialFormatContentType + ) + } + get("$getContentByIdRoute/{id}") { + val id = call.parameters["id"].also { + if (it == null) call.respond(HttpStatusCode.BadRequest, "Request must contains id in route") + } ?: return@get + call.respondBytes( + standardKtorSerialFormat.dump( + RegisteredContent.serializer().nullable, + proxyTo.getContentById(id) + ), + standardKtorSerialFormatContentType + ) + } + get(getContentByPaginationRoute) { + val pagination = call.request.queryParameters.extractPagination + call.respondBytes( + standardKtorSerialFormat.dump( + registeredContentPaginationResultSerializer, + proxyTo.getContentByPagination(pagination) + ) + ) + } +} + +class ReadContentRepoRoutingConfigurator( + private val proxyTo: ReadContentRepo +) : ApplicationRoutingConfigurator.Element { + override fun Route.invoke() { + configureReadContentRepoRoutes(proxyTo) + } +} diff --git a/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/WriteContentRepoRoutingConfigurator.kt b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/WriteContentRepoRoutingConfigurator.kt new file mode 100644 index 00000000..1fa2eb22 --- /dev/null +++ b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/content/WriteContentRepoRoutingConfigurator.kt @@ -0,0 +1,63 @@ +package com.insanusmokrassar.postssystem.core.ktor.server.content + +import com.insanusmokrassar.postssystem.core.content.* +import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo +import com.insanusmokrassar.postssystem.core.ktor.* +import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator +import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling +import com.insanusmokrassar.postssystem.ktor.server.standardKtorSerialFormatContentType +import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat +import io.ktor.application.call +import io.ktor.response.respondBytes +import io.ktor.routing.Route +import io.ktor.routing.post +import io.ktor.util.toByteArray +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer + +fun Route.configureWriteContentRepoRoutes( + proxyTo: WriteContentRepo +) { + includeWebsocketHandling(contentCreatedFlowRoute, proxyTo.contentCreatedFlow) { + standardKtorSerialFormat.dump(RegisteredContent.serializer(), it) + } + includeWebsocketHandling(contentDeletedFlowRoute, proxyTo.contentDeletedFlow) { + standardKtorSerialFormat.dump(RegisteredContent.serializer(), it) + } + post(registerContentRoute) { + val content = standardKtorSerialFormat.load( + Content.serializer(), + call.request.receiveChannel().toByteArray() + ) + val registered = proxyTo.registerContent(content) + call.respondBytes( + standardKtorSerialFormat.dump( + RegisteredContent.serializer().nullable, + registered + ), + standardKtorSerialFormatContentType + ) + } + post(deleteContentRoute) { + val contentId = standardKtorSerialFormat.load( + ContentId.serializer(), + call.request.receiveChannel().toByteArray() + ) + val isDeleted = proxyTo.deleteContent(contentId) + call.respondBytes( + standardKtorSerialFormat.dump( + Boolean.serializer(), + isDeleted + ), + standardKtorSerialFormatContentType + ) + } +} + +class WriteContentRepoRoutingConfigurator( + private val proxyTo: WriteContentRepo +) : ApplicationRoutingConfigurator.Element { + override fun Route.invoke() { + configureWriteContentRepoRoutes(proxyTo) + } +} diff --git a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/PaginationInUrl.kt b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/PaginationInUrl.kt new file mode 100644 index 00000000..b30b5691 --- /dev/null +++ b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/PaginationInUrl.kt @@ -0,0 +1,10 @@ +package com.insanusmokrassar.postssystem.ktor.server + +import com.insanusmokrassar.postssystem.utils.common.pagination.* +import io.ktor.http.Parameters + +val Parameters.extractPagination: Pagination + get() = SimplePagination( + get("page") ?.toIntOrNull() ?: 0, + get("size") ?.toIntOrNull() ?: defaultMediumPageSize + ) diff --git a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/configurators/ApplicationRoutingConfigurator.kt b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/configurators/ApplicationRoutingConfigurator.kt index 0e56e3b3..8ec15a65 100644 --- a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/configurators/ApplicationRoutingConfigurator.kt +++ b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/configurators/ApplicationRoutingConfigurator.kt @@ -1,6 +1,7 @@ package com.insanusmokrassar.postssystem.ktor.server.configurators import io.ktor.application.* +import io.ktor.routing.Route import io.ktor.routing.Routing import kotlinx.serialization.ContextualSerialization import kotlinx.serialization.Serializable @@ -9,7 +10,7 @@ import kotlinx.serialization.Serializable class ApplicationRoutingConfigurator( private val elements: List<@ContextualSerialization Element> ) : KtorApplicationConfigurator { - interface Element { operator fun Routing.invoke() } + interface Element { operator fun Route.invoke() } override fun Application.configure() { try { diff --git a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/standardKtorSerialFormatContentType.kt b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/standardKtorSerialFormatContentType.kt new file mode 100644 index 00000000..e7e0e422 --- /dev/null +++ b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/standardKtorSerialFormatContentType.kt @@ -0,0 +1,5 @@ +package com.insanusmokrassar.postssystem.ktor.server + +import io.ktor.http.ContentType + +val standardKtorSerialFormatContentType = ContentType.Application.Cbor