diff options
author | Robert Jaros <rjaros@finn.pl> | 2019-04-10 18:24:14 +0200 |
---|---|---|
committer | Robert Jaros <rjaros@finn.pl> | 2019-04-10 18:24:14 +0200 |
commit | 9374d0df9c462493e9cb91c846e4f820b3325f7b (patch) | |
tree | b8654b6b6bb3d31fc2fae50195faa8096749f8a7 /kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision | |
parent | fc8023bf8eb4c17b7fc1e77bb057a7c3df19eb0d (diff) | |
download | kvision-9374d0df9c462493e9cb91c846e4f820b3325f7b.tar.gz kvision-9374d0df9c462493e9cb91c846e4f820b3325f7b.tar.bz2 kvision-9374d0df9c462493e9cb91c846e4f820b3325f7b.zip |
Websockets support for Spring Boot and Jooby.
Diffstat (limited to 'kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision')
2 files changed, 35 insertions, 10 deletions
diff --git a/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVModules.kt b/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVModules.kt index a5e22b2d..34fff02d 100644 --- a/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVModules.kt +++ b/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVModules.kt @@ -45,6 +45,9 @@ import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.channels.SendChannel import kotlin.coroutines.CoroutineContext +/** + * Initialization function for Ktor server. + */ fun Application.kvisionInit(vararg modules: Module) { install(ContentNegotiation) { jackson() @@ -69,18 +72,21 @@ val injectorKey = AttributeKey<Injector>("injector") val ApplicationCall.injector: Injector get() = attributes[injectorKey] -class CallModule(private val call: ApplicationCall) : AbstractModule() { +internal class CallModule(private val call: ApplicationCall) : AbstractModule() { override fun configure() { bind(ApplicationCall::class.java).toInstance(call) } } -class MainModule(private val application: Application) : AbstractModule() { +internal class MainModule(private val application: Application) : AbstractModule() { override fun configure() { bind(Application::class.java).toInstance(application) } } +/** + * @suppress internal class + */ class WsSessionModule(private val webSocketSession: WebSocketServerSession) : AbstractModule() { override fun configure() { @@ -88,12 +94,18 @@ class WsSessionModule(private val webSocketSession: WebSocketServerSession) : } } +/** + * @suppress internal class + */ class DummyWsSessionModule : AbstractModule() { override fun configure() { bind(WebSocketServerSession::class.java).toInstance(DummyWebSocketServerSession()) } } +/** + * @suppress internal class + */ @Suppress("UNUSED_PARAMETER") class DummyWebSocketServerSession : WebSocketServerSession { override val call: ApplicationCall diff --git a/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt index aca5d2f0..11771cfa 100644 --- a/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt +++ b/kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -36,6 +36,7 @@ import io.ktor.routing.get import io.ktor.routing.options import io.ktor.routing.post import io.ktor.routing.put +import io.ktor.util.KtorExperimentalAPI import io.ktor.util.pipeline.PipelineContext import io.ktor.websocket.WebSocketServerSession import io.ktor.websocket.webSocket @@ -45,7 +46,6 @@ import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.channels.SendChannel import kotlinx.coroutines.channels.filterNotNull import kotlinx.coroutines.channels.map -import kotlinx.coroutines.channels.mapNotNull import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import org.slf4j.Logger @@ -55,6 +55,7 @@ import kotlin.reflect.KClass /** * Multiplatform service manager for Ktor. */ +@KtorExperimentalAPI @UseExperimental(ExperimentalCoroutinesApi::class) @Suppress("LargeClass") actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: KClass<T>) { @@ -374,15 +375,17 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: route: String? ) { val routeDef = "route${this::class.simpleName}${counter++}" - webSocketRequests["/kv/$routeDef"] = { + webSocketRequests["/kvws/$routeDef"] = { val wsInjector = call.injector.createChildInjector(WsSessionModule(this)) val service = wsInjector.getInstance(serviceClass.java) - val requestChannel = incoming.mapNotNull { it as? Frame.Text }.map { - val jsonRpcRequest = getParameter<JsonRpcRequest>(it.readText()) - if (jsonRpcRequest.params.size == 1) { - getParameter<PAR1>(jsonRpcRequest.params[0]) - } else { - null + val requestChannel = incoming.map { + (it as? Frame.Text)?.readText()?.let { text -> + val jsonRpcRequest = getParameter<JsonRpcRequest>(text) + if (jsonRpcRequest.params.size == 1) { + getParameter<PAR1>(jsonRpcRequest.params[0]) + } else { + null + } } }.filterNotNull() val responseChannel = Channel<PAR2>() @@ -452,6 +455,9 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } } + /** + * @suppress Internal method + */ fun addRoute( method: HttpMethod, path: String, @@ -466,6 +472,9 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } } + /** + * @suppress Internal method + */ protected inline fun <reified T> getParameter(str: String?): T { return str?.let { if (T::class == String::class) { @@ -477,6 +486,10 @@ actual open class KVServiceManager<T : Any> actual constructor(val serviceClass: } } +/** + * A function to generate routes based on definitions from the service manager. + */ +@KtorExperimentalAPI fun <T : Any> Route.applyRoutes(serviceManager: KVServiceManager<T>) { serviceManager.getRequests.forEach { (path, handler) -> get(path, handler) |