Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support CIO server for wasm-js and js #4466

Open
wants to merge 11 commits into
base: 3.1.0-eap
Choose a base branch
from
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/JsConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fun Project.configureJs() {
internal fun KotlinJsSubTargetDsl.useMochaForTests() {
testTask {
useMocha {
timeout = "10000"
timeout = "60000"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've increased timeout for JS tests here, as I have no idea from where the issue in JS engine comming :)

For some reason, the behavior in Js/WasmJs differs here - I can't understand if it's the issue in ktor-network implementation or in some expect-actual, or in some other thing...

}
}
}
Expand Down
2 changes: 1 addition & 1 deletion ktor-server/ktor-server-cio/api/ktor-server-cio.klib.api
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Klib ABI Dump
// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64]
// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64]
// Rendering settings:
// - Signature version: 2
// - Show manifest properties: true
Expand Down
5 changes: 2 additions & 3 deletions ktor-server/ktor-server-cio/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
description = ""

kotlin.sourceSets {
jvmAndPosixMain {
commonMain {
dependencies {
api(project(":ktor-server:ktor-server-core"))
api(project(":ktor-http:ktor-http-cio"))
api(project(":ktor-shared:ktor-websockets"))
api(project(":ktor-network"))
}
}
jvmAndPosixTest {
commonTest {
dependencies {
api(project(":ktor-server:ktor-server-core"))
api(project(":ktor-client:ktor-client-cio"))
api(project(":ktor-server:ktor-server-test-suites"))
api(project(":ktor-server:ktor-server-test-base"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public class CIOApplicationEngine(
return this
}

override fun start(wait: Boolean): ApplicationEngine = runBlocking { startSuspend(wait) }
override fun start(wait: Boolean): ApplicationEngine = runBlockingBridge { startSuspend(wait) }

override suspend fun stopSuspend(gracePeriodMillis: Long, timeoutMillis: Long) {
stopRequest.complete()
Expand All @@ -96,7 +96,7 @@ public class CIOApplicationEngine(
}
}

override fun stop(gracePeriodMillis: Long, timeoutMillis: Long): Unit = runBlocking {
override fun stop(gracePeriodMillis: Long, timeoutMillis: Long): Unit = runBlockingBridge {
stopSuspend(gracePeriodMillis, timeoutMillis)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import io.ktor.server.engine.internal.*
import io.ktor.util.logging.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.io.IOException
import kotlinx.io.*
import kotlin.time.Duration.Companion.seconds

private val LOGGER = KtorSimpleLogger("io.ktor.server.cio.HttpServer")

/**
* Start a http server with [settings] invoking [handler] for every request
*/
Expand All @@ -37,18 +39,14 @@ public fun CoroutineScope.httpServer(
val selector = SelectorManager(coroutineContext)
val timeout = settings.connectionIdleTimeoutSeconds.seconds

val logger = KtorSimpleLogger(
HttpServer::class.simpleName ?: HttpServer::class.qualifiedName ?: HttpServer::class.toString()
)

val acceptJob = launch(serverJob + CoroutineName("accept-${settings.port}")) {
aSocket(selector).tcp().bind(settings.host, settings.port) {
reuseAddress = settings.reuseAddress
}.use { server ->
socket.complete(server)

val exceptionHandler = coroutineContext[CoroutineExceptionHandler]
?: DefaultUncaughtExceptionHandler(logger)
?: DefaultUncaughtExceptionHandler(LOGGER)

val connectionScope = CoroutineScope(
coroutineContext +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ package io.ktor.server.cio.internal
import kotlinx.coroutines.*

internal expect val Dispatchers.IOBridge: CoroutineDispatcher

internal expect fun <T> runBlockingBridge(block: suspend CoroutineScope.() -> T): T
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.ktor.http.*
import io.ktor.http.cio.*
import io.ktor.server.cio.*
import io.ktor.server.cio.backend.*
import io.ktor.server.cio.internal.*
import io.ktor.util.date.*
import io.ktor.utils.io.*
import io.ktor.utils.io.core.*
Expand All @@ -29,7 +30,7 @@ private val notFound404_11 = RequestResponseBuilder().apply {
* This is just an example demonstrating how to create CIO low-level http server
*/
@OptIn(DelicateCoroutinesApi::class)
fun main() {
fun example() {
val settings = HttpServerSettings()

GlobalScope.launch {
Expand Down Expand Up @@ -64,7 +65,7 @@ fun main() {
}
)

runBlocking {
runBlockingBridge {
server.rootServerJob.join()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.server.cio.internal

import kotlinx.coroutines.*

internal actual val Dispatchers.IOBridge: CoroutineDispatcher
get() = Default

internal actual fun <T> runBlockingBridge(block: suspend CoroutineScope.() -> T): T =
error("runBlocking is not supported on JS and WASM")
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ import kotlinx.coroutines.*

internal actual val Dispatchers.IOBridge: CoroutineDispatcher
get() = IO

internal actual fun <T> runBlockingBridge(block: suspend CoroutineScope.() -> T): T = runBlocking(block = block)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import io.ktor.network.sockets.*
import io.ktor.util.network.*

internal actual fun SocketAddress.toNetworkAddress(): NetworkAddress {
val inetAddress = this as? InetSocketAddress ?: error("Expected inet socket address")
return NetworkAddress(inetAddress.hostname, inetAddress.port)
check(this is InetSocketAddress) { "Expected inet socket address" }
return NetworkAddress(hostname, port)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ import kotlinx.coroutines.*

internal actual val Dispatchers.IOBridge: CoroutineDispatcher
get() = IO
osipxd marked this conversation as resolved.
Show resolved Hide resolved

internal actual fun <T> runBlockingBridge(block: suspend CoroutineScope.() -> T): T = runBlocking(block = block)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package io.ktor.server.test.base

import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
Expand Down Expand Up @@ -130,7 +131,6 @@ actual constructor(
val starting = GlobalScope.async {
server.startSuspend(wait = false)
_port = server.engine.resolvedConnectors().first().port
delay(500)
}

return try {
Expand Down Expand Up @@ -159,7 +159,7 @@ actual constructor(
builder: suspend HttpRequestBuilder.() -> Unit,
block: suspend HttpResponse.(Int) -> Unit
) {
HttpClient {
HttpClient(CIO) {
followRedirects = false
expectSuccess = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ actual constructor(
// as far as we have retry loop on call side
val starting = GlobalScope.async {
server.start(wait = false)
delay(500)
// await for a server to be started
server.engine.resolvedConnectors()
}

return try {
Expand Down
7 changes: 1 addition & 6 deletions ktor-server/ktor-server-test-host/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,13 @@ val jetty_alpn_boot_version: String? by extra
kotlin.sourceSets {
commonMain {
dependencies {
api(project(":ktor-client:ktor-client-cio"))
api(project(":ktor-server:ktor-server-core"))
api(project(":ktor-client:ktor-client-core"))
api(project(":ktor-test-dispatcher"))
}
}

jvmAndPosixMain {
dependencies {
api(project(":ktor-client:ktor-client-cio"))
}
}

jvmMain {
dependencies {
api(project(":ktor-network:ktor-network-tls"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.ktor.client.request.*
import io.ktor.util.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.io.*
import io.ktor.network.sockets.SocketTimeoutException as NetworkSocketTimeoutException

/**
* [on] function receiver object
Expand Down Expand Up @@ -67,10 +67,3 @@ internal fun Throwable.mapToKtor(data: HttpRequestData): Throwable = when {
cause?.rootCause is NetworkSocketTimeoutException -> SocketTimeoutException(data, cause?.rootCause)
else -> this
}

// There are two SocketTimeoutException in ktor:
// * io.ktor.network.sockets.SocketTimeoutException
// * io.ktor.client.network.sockets.SocketTimeoutException
// on JVM they both are java.net.SocketTimeoutException, but on other targets it's not true
// additionally `network.sockets` exception is in `ktor-network` modules which don't have support for js/wasm target
internal expect class NetworkSocketTimeoutException(message: String) : IOException

This file was deleted.

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion ktor-server/ktor-server-test-suites/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ kotlin.sourceSets {
implementation(project(":ktor-server:ktor-server-plugins:ktor-server-status-pages"))
implementation(project(":ktor-server:ktor-server-plugins:ktor-server-hsts"))
implementation(project(":ktor-server:ktor-server-plugins:ktor-server-websockets"))
implementation(project(":ktor-server:ktor-server-test-base"))
api(project(":ktor-server:ktor-server-test-base"))
}
}

Expand Down