aboutsummaryrefslogtreecommitdiff
path: root/kvision-modules/kvision-server-ktor/src
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2019-04-10 18:24:14 +0200
committerRobert Jaros <rjaros@finn.pl>2019-04-10 18:24:14 +0200
commit9374d0df9c462493e9cb91c846e4f820b3325f7b (patch)
treeb8654b6b6bb3d31fc2fae50195faa8096749f8a7 /kvision-modules/kvision-server-ktor/src
parentfc8023bf8eb4c17b7fc1e77bb057a7c3df19eb0d (diff)
downloadkvision-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')
-rw-r--r--kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVModules.kt16
-rw-r--r--kvision-modules/kvision-server-ktor/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt29
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)