complete client-server part for core api

This commit is contained in:
InsanusMokrassar 2020-08-14 13:17:27 +06:00
parent 93bd094823
commit 8c3a48db99
8 changed files with 234 additions and 15 deletions

View File

@ -1,18 +1,27 @@
package com.insanusmokrassar.postssystem.core.ktor.client.post package com.insanusmokrassar.postssystem.core.ktor.client.post
import com.insanusmokrassar.postssystem.core.ktor.postsRootRoute
import com.insanusmokrassar.postssystem.core.post.repo.* import com.insanusmokrassar.postssystem.core.post.repo.*
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.WebSockets import io.ktor.client.features.websocket.WebSockets
class PostsRepoKtorClient( class PostsRepoKtorClient private constructor(
baseUrl: String, readPostsRepo: ReadPostsRepo,
client: HttpClient = HttpClient { writePostsRepo: WritePostsRepo
install(WebSockets) ) : PostsRepo, ReadPostsRepo by readPostsRepo, WritePostsRepo by writePostsRepo {
} constructor(
) : PostsRepo, ReadPostsRepo by ReadPostsRepoKtorClient( baseUrl: String,
baseUrl, client: HttpClient = HttpClient {
client install(WebSockets)
), WritePostsRepo by WritePostsRepoKtorClient( }
baseUrl, ) : this(
client ReadPostsRepoKtorClient(
) "${baseUrl}/$postsRootRoute",
client
),
WritePostsRepoKtorClient(
"${baseUrl}/$postsRootRoute",
client
)
)
}

View File

@ -43,14 +43,14 @@ class WritePostsRepoKtorClient (
} }
override suspend fun deletePost(id: PostId): Boolean = client.post<ByteArray> { override suspend fun deletePost(id: PostId): Boolean = client.post<ByteArray> {
url("$baseUrl/$createPostRoute") url("$baseUrl/$deletePostRoute")
body = standardKtorSerialFormat.dump(PostId.serializer(), id) body = standardKtorSerialFormat.dump(PostId.serializer(), id)
}.let { }.let {
standardKtorSerialFormat.load(Boolean.serializer(), it) standardKtorSerialFormat.load(Boolean.serializer(), it)
} }
override suspend fun updatePostContent(postId: PostId, post: Post): Boolean = client.post<ByteArray> { override suspend fun updatePostContent(postId: PostId, post: Post): Boolean = client.post<ByteArray> {
url("$baseUrl/$createPostRoute") url("$baseUrl/$updatePostContentRoute")
body = standardKtorSerialFormat.dump(UpdatePostObject.serializer(), UpdatePostObject(postId, post)) body = standardKtorSerialFormat.dump(UpdatePostObject.serializer(), UpdatePostObject(postId, post))
}.let { }.let {
standardKtorSerialFormat.load(Boolean.serializer(), it) standardKtorSerialFormat.load(Boolean.serializer(), it)

View File

@ -1,5 +1,7 @@
package com.insanusmokrassar.postssystem.core.ktor package com.insanusmokrassar.postssystem.core.ktor
const val postsRootRoute = "post"
const val getPostsIdsRoute = "getPostsIds" const val getPostsIdsRoute = "getPostsIds"
const val getPostByIdRoute = "getPostById" const val getPostByIdRoute = "getPostById"
const val getPostsByContentRoute = "getPostsByContent" const val getPostsByContentRoute = "getPostsByContent"

View File

@ -1,5 +1,6 @@
package com.insanusmokrassar.postssystem.core.ktor.server.content 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.RegisteredContent
import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo
import com.insanusmokrassar.postssystem.core.ktor.* import com.insanusmokrassar.postssystem.core.ktor.*
@ -24,7 +25,7 @@ fun Route.configureReadContentRepoRoutes(
) )
} }
get("$getContentByIdRoute/{id}") { 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") if (it == null) call.respond(HttpStatusCode.BadRequest, "Request must contains id in route")
} ?: return@get } ?: return@get
call.respondBytes( call.respondBytes(

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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) }
)