From 8c3a48db99148c29d2e2f68b9a700606913367f6 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 14 Aug 2020 13:17:27 +0600 Subject: [PATCH] complete client-server part for core api --- .../ktor/client/post/PostsRepoKtorClient.kt | 33 ++++--- .../client/post/WritePostsRepoKtorClient.kt | 4 +- .../postssystem/core/ktor/PostRoutes.kt | 2 + .../ReadContentRepoRoutingConfigurator.kt | 3 +- .../post/PostsRepoRoutingConfigurator.kt | 24 +++++ .../post/ReadPostsRepoRoutingConfigurator.kt | 93 +++++++++++++++++++ .../post/WritePostsRepoRoutingConfigurator.kt | 79 ++++++++++++++++ .../ktor/server/FromToDateTimeInUrl.kt | 11 +++ 8 files changed, 234 insertions(+), 15 deletions(-) create mode 100644 core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/PostsRepoRoutingConfigurator.kt create mode 100644 core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/ReadPostsRepoRoutingConfigurator.kt create mode 100644 core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/WritePostsRepoRoutingConfigurator.kt create mode 100644 ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/FromToDateTimeInUrl.kt diff --git a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/PostsRepoKtorClient.kt b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/PostsRepoKtorClient.kt index d60c795a..924607e9 100644 --- a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/PostsRepoKtorClient.kt +++ b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/PostsRepoKtorClient.kt @@ -1,18 +1,27 @@ package com.insanusmokrassar.postssystem.core.ktor.client.post +import com.insanusmokrassar.postssystem.core.ktor.postsRootRoute import com.insanusmokrassar.postssystem.core.post.repo.* import io.ktor.client.HttpClient import io.ktor.client.features.websocket.WebSockets -class PostsRepoKtorClient( - baseUrl: String, - client: HttpClient = HttpClient { - install(WebSockets) - } -) : PostsRepo, ReadPostsRepo by ReadPostsRepoKtorClient( - baseUrl, - client -), WritePostsRepo by WritePostsRepoKtorClient( - baseUrl, - client -) +class PostsRepoKtorClient private constructor( + readPostsRepo: ReadPostsRepo, + writePostsRepo: WritePostsRepo +) : PostsRepo, ReadPostsRepo by readPostsRepo, WritePostsRepo by writePostsRepo { + constructor( + baseUrl: String, + client: HttpClient = HttpClient { + install(WebSockets) + } + ) : this( + ReadPostsRepoKtorClient( + "${baseUrl}/$postsRootRoute", + client + ), + WritePostsRepoKtorClient( + "${baseUrl}/$postsRootRoute", + client + ) + ) +} diff --git a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/WritePostsRepoKtorClient.kt b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/WritePostsRepoKtorClient.kt index 8e8f2dc6..b4d271ce 100644 --- a/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/WritePostsRepoKtorClient.kt +++ b/core/ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/client/post/WritePostsRepoKtorClient.kt @@ -43,14 +43,14 @@ class WritePostsRepoKtorClient ( } override suspend fun deletePost(id: PostId): Boolean = client.post { - url("$baseUrl/$createPostRoute") + url("$baseUrl/$deletePostRoute") body = standardKtorSerialFormat.dump(PostId.serializer(), id) }.let { standardKtorSerialFormat.load(Boolean.serializer(), it) } override suspend fun updatePostContent(postId: PostId, post: Post): Boolean = client.post { - url("$baseUrl/$createPostRoute") + url("$baseUrl/$updatePostContentRoute") body = standardKtorSerialFormat.dump(UpdatePostObject.serializer(), UpdatePostObject(postId, post)) }.let { standardKtorSerialFormat.load(Boolean.serializer(), it) diff --git a/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/PostRoutes.kt b/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/PostRoutes.kt index 69633e2e..2e3f6c64 100644 --- a/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/PostRoutes.kt +++ b/core/ktor/common/src/commonMain/kotlin/com/insanusmokrassar/postssystem/core/ktor/PostRoutes.kt @@ -1,5 +1,7 @@ package com.insanusmokrassar.postssystem.core.ktor +const val postsRootRoute = "post" + const val getPostsIdsRoute = "getPostsIds" const val getPostByIdRoute = "getPostById" const val getPostsByContentRoute = "getPostsByContent" 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 index c46205de..01e5b467 100644 --- 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 @@ -1,5 +1,6 @@ package com.insanusmokrassar.postssystem.core.ktor.server.content +import com.insanusmokrassar.postssystem.core.content.ContentId import com.insanusmokrassar.postssystem.core.content.RegisteredContent import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo import com.insanusmokrassar.postssystem.core.ktor.* @@ -24,7 +25,7 @@ fun Route.configureReadContentRepoRoutes( ) } get("$getContentByIdRoute/{id}") { - val id = call.parameters["id"].also { + val id: ContentId = call.parameters["id"].also { if (it == null) call.respond(HttpStatusCode.BadRequest, "Request must contains id in route") } ?: return@get call.respondBytes( diff --git a/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/PostsRepoRoutingConfigurator.kt b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/PostsRepoRoutingConfigurator.kt new file mode 100644 index 00000000..beb217c8 --- /dev/null +++ b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/PostsRepoRoutingConfigurator.kt @@ -0,0 +1,24 @@ +package com.insanusmokrassar.postssystem.core.ktor.server.post + +import com.insanusmokrassar.postssystem.core.ktor.postsRootRoute +import com.insanusmokrassar.postssystem.core.post.repo.PostsRepo +import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator +import io.ktor.routing.Route +import io.ktor.routing.route + +fun Route.configurePostsRepoRoutes( + proxyTo: PostsRepo +) { + route(postsRootRoute) { + configureReadPostsRepoRoutes(proxyTo) + configureWritePostsRepoRoutes(proxyTo) + } +} + +class PostsRepoRoutingConfigurator( + private val proxyTo: PostsRepo +) : ApplicationRoutingConfigurator.Element { + override fun Route.invoke() { + configurePostsRepoRoutes(proxyTo) + } +} diff --git a/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/ReadPostsRepoRoutingConfigurator.kt b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/ReadPostsRepoRoutingConfigurator.kt new file mode 100644 index 00000000..8a382995 --- /dev/null +++ b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/ReadPostsRepoRoutingConfigurator.kt @@ -0,0 +1,93 @@ +package com.insanusmokrassar.postssystem.core.ktor.server.post + +import com.insanusmokrassar.postssystem.core.content.ContentId +import com.insanusmokrassar.postssystem.core.ktor.* +import com.insanusmokrassar.postssystem.core.post.PostId +import com.insanusmokrassar.postssystem.core.post.RegisteredPost +import com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo +import com.insanusmokrassar.postssystem.ktor.server.* +import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator +import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat +import com.insanusmokrassar.postssystem.utils.common.MAX_DATE +import com.insanusmokrassar.postssystem.utils.common.MIN_DATE +import io.ktor.application.call +import io.ktor.http.HttpStatusCode +import io.ktor.response.respond +import io.ktor.response.respondBytes +import io.ktor.routing.Route +import io.ktor.routing.get +import kotlinx.serialization.builtins.nullable + +fun Route.configureReadPostsRepoRoutes( + proxyTo: ReadPostsRepo +) { + get(getPostsIdsRoute) { + call.respondBytes( + standardKtorSerialFormat.dump(postIdsSerializer, proxyTo.getPostsIds()), + standardKtorSerialFormatContentType + ) + } + get("$getPostByIdRoute/{id}") { + val id: PostId = call.parameters["id"].also { + if (it == null) { + call.respond(HttpStatusCode.BadRequest, "request must contains id") + } + } ?: return@get + call.respondBytes( + standardKtorSerialFormat.dump( + RegisteredPost.serializer().nullable, + proxyTo.getPostById(id) + ), + standardKtorSerialFormatContentType + ) + } + get("$getPostsByContentRoute/{id}") { + val id: ContentId = call.parameters["id"].also { + if (it == null) { + call.respond(HttpStatusCode.BadRequest, "request must contains id") + } + } ?: return@get + call.respondBytes( + standardKtorSerialFormat.dump( + registeredPostsListSerializer, + proxyTo.getPostsByContent(id) + ), + standardKtorSerialFormatContentType + ) + } + get(getPostsByCreatingDatesRoute) { + val fromToDateTime = call.request.queryParameters.extractFromToDateTime + val pagination = call.request.queryParameters.extractPagination + + call.respondBytes( + standardKtorSerialFormat.dump( + registeredPostsPaginationResultSerializer, + proxyTo.getPostsByCreatingDates( + fromToDateTime.first ?: MIN_DATE, + fromToDateTime.second ?: MAX_DATE, + pagination + ) + ), + standardKtorSerialFormatContentType + ) + } + get(getPostsByPaginationRoute) { + val pagination = call.request.queryParameters.extractPagination + + call.respondBytes( + standardKtorSerialFormat.dump( + registeredPostsPaginationResultSerializer, + proxyTo.getPostsByPagination(pagination) + ), + standardKtorSerialFormatContentType + ) + } +} + +class ReadPostsRepoRoutingConfigurator( + private val proxyTo: ReadPostsRepo +) : ApplicationRoutingConfigurator.Element { + override fun Route.invoke() { + configureReadPostsRepoRoutes(proxyTo) + } +} diff --git a/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/WritePostsRepoRoutingConfigurator.kt b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/WritePostsRepoRoutingConfigurator.kt new file mode 100644 index 00000000..b4617082 --- /dev/null +++ b/core/ktor/server/src/main/kotlin/com/insanusmokrassar/postssystem/core/ktor/server/post/WritePostsRepoRoutingConfigurator.kt @@ -0,0 +1,79 @@ +package com.insanusmokrassar.postssystem.core.ktor.server.post + +import com.insanusmokrassar.postssystem.core.ktor.* +import com.insanusmokrassar.postssystem.core.post.* +import com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo +import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator +import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling +import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat +import io.ktor.application.call +import io.ktor.response.respondBytes +import io.ktor.routing.* +import io.ktor.util.toByteArray +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer + +fun Route.configureWritePostsRepoRoutes( + proxyTo: WritePostsRepo +) { + includeWebsocketHandling(postCreatedFlowRoute, proxyTo.postCreatedFlow) { + standardKtorSerialFormat.dump(RegisteredPost.serializer(), it) + } + includeWebsocketHandling(postDeletedFlowRoute, proxyTo.postDeletedFlow) { + standardKtorSerialFormat.dump(RegisteredPost.serializer(), it) + } + includeWebsocketHandling(postUpdatedFlowRoute, proxyTo.postUpdatedFlow) { + standardKtorSerialFormat.dump(RegisteredPost.serializer(), it) + } + + post(createPostRoute) { + val post = standardKtorSerialFormat.load( + Post.serializer(), + call.request.receiveChannel().toByteArray() + ) + + call.respondBytes( + standardKtorSerialFormat.dump( + RegisteredPost.serializer().nullable, + proxyTo.createPost(post) + ) + ) + } + + post(deletePostRoute) { + val postId = standardKtorSerialFormat.load( + PostId.serializer(), + call.request.receiveChannel().toByteArray() + ) + + call.respondBytes( + standardKtorSerialFormat.dump( + Boolean.serializer(), + proxyTo.deletePost(postId) + ) + ) + } + + post(updatePostContentRoute) { + val updatePostObject = standardKtorSerialFormat.load( + UpdatePostObject.serializer(), + call.request.receiveChannel().toByteArray() + ) + + call.respondBytes( + standardKtorSerialFormat.dump( + Boolean.serializer(), + proxyTo.updatePostContent(updatePostObject.postId, updatePostObject.post) + ) + ) + } +} + +class WritePostsRepoRoutingConfigurator( + private val proxyTo: WritePostsRepo +) : ApplicationRoutingConfigurator.Element { + override fun Route.invoke() { + configureWritePostsRepoRoutes(proxyTo) + } + +} diff --git a/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/FromToDateTimeInUrl.kt b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/FromToDateTimeInUrl.kt new file mode 100644 index 00000000..d35a4a96 --- /dev/null +++ b/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server/FromToDateTimeInUrl.kt @@ -0,0 +1,11 @@ +package com.insanusmokrassar.postssystem.ktor.server + +import com.insanusmokrassar.postssystem.ktor.FromToDateTime +import com.soywiz.klock.DateTime +import io.ktor.http.Parameters + +val Parameters.extractFromToDateTime: FromToDateTime + get() = FromToDateTime( + get("from") ?.toDoubleOrNull() ?.let { DateTime(it) }, + get("to") ?.toDoubleOrNull() ?.let { DateTime(it) } + )