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

KTOR-7866: Update Kotlin to v2.1.0 #4512

Open
wants to merge 22 commits into
base: 3.1.0-eap
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e846851
KTOR-7606 Make Closable implement AutoCloseable (#4414)
osipxd Oct 28, 2024
3ea38f5
KTOR-7586 Improve parsing of supported media types (#4410)
anton-erofeev Oct 30, 2024
60ea614
Version 3.1.0-SNAPSHOT
osipxd Oct 30, 2024
31fedde
KTOR-7586 Fix MimesTest doesn't compile on JS target (#4438)
osipxd Oct 31, 2024
0441dc6
KTOR-6004 Support TCP and Unix socket for wasm-js and js via NodeJS (…
whyoleg Oct 31, 2024
8de47cf
KTOR-7663 Add `bind` overload for UDPSocketBuilder (#4456)
marychatte Nov 8, 2024
49e756a
KTOR-7675 Support CIO client for wasm-js and js (#4441)
whyoleg Nov 8, 2024
2fde22b
KTOR-7620 Make Url class @Serializable and JVM Serializable (#4421)
wkornewald Nov 12, 2024
c27cd75
KTOR-6632 Support receiving multipart data with Ktor client (#4458)
e5l Nov 13, 2024
5d4c1b4
KTOR-7435 Add serialization for SSE (#4363)
marychatte Nov 15, 2024
06fb3fb
Update dependency io.micrometer:micrometer-core to v1.14.1 (#4472)
renovate[bot] Nov 18, 2024
ea06356
Use static libcurl build with conan (#4445)
whyoleg Nov 19, 2024
00b4213
KTOR-7644 Make re-auth status codes configurable (#4420)
wkornewald Nov 19, 2024
a216f3a
KTOR-7679 Allow disabling body decoding on server (#4444)
e5l Nov 19, 2024
74aa326
KTOR-7359 Implement a suspending version of EmbeddedServer.start and …
whyoleg Nov 19, 2024
9b0acca
KTOR-7470 receiveMultipart throw UnsupportedMediaTypeException (#4339)
stokado Nov 21, 2024
ec1071d
KTOR-7722 content negotiation client accept header control (#4462)
rocketraman Nov 22, 2024
f6e4926
KTOR-7893 Add favicon to Swagger UI (#4528)
marychatte Dec 5, 2024
cc3f8f8
Fix no-blank-line-before-rbrace
osipxd Dec 11, 2024
857b2ea
Update Kotlin to v2.1.0
renovate[bot] Nov 27, 2024
84f8c55
Update yarn.lock
osipxd Nov 27, 2024
27d125b
Update kotlinter to 5.0.0
osipxd Dec 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
KTOR-6004 Support TCP and Unix socket for wasm-js and js via NodeJS (#…
…4411)

* Drop `jvmAndNix` shared source set
* Commonize `ktor-network` and `ktor-network-tls`
* Support TCP and Unix sockets for wasm-js and js on Node
* Move `supportsUnixDomainSockets` to posix and use Platform instead of expect/actual
whyoleg authored and osipxd committed Dec 12, 2024
commit 0441dc606e1570bc6944b9058534bd0fe261f274
5 changes: 5 additions & 0 deletions buildSrc/src/main/kotlin/TargetsConfig.kt
Original file line number Diff line number Diff line change
@@ -114,6 +114,11 @@ private val hierarchyTemplate = KotlinHierarchyTemplate {
group("windows")
group("macos")
}

group("nonJvm") {
group("posix")
group("jsAndWasmShared")
}
}
}

26 changes: 16 additions & 10 deletions ktor-network/api/ktor-network.klib.api
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// 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]
// Alias: native => [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64]
// Rendering settings:
// - Signature version: 2
// - Show manifest properties: true
@@ -36,11 +37,6 @@ abstract interface <#A: out io.ktor.network.sockets/Configurable<#A, #B>, #B: io
open fun configure(kotlin/Function1<#B, kotlin/Unit>): #A // io.ktor.network.sockets/Configurable.configure|configure(kotlin.Function1<1:1,kotlin.Unit>){}[0]
}

abstract interface io.ktor.network.selector/Selectable { // io.ktor.network.selector/Selectable|null[0]
abstract val descriptor // io.ktor.network.selector/Selectable.descriptor|{}descriptor[0]
abstract fun <get-descriptor>(): kotlin/Int // io.ktor.network.selector/Selectable.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
}

abstract interface io.ktor.network.selector/SelectorManager : io.ktor.utils.io.core/Closeable, kotlinx.coroutines/CoroutineScope { // io.ktor.network.selector/SelectorManager|null[0]
abstract fun notifyClosed(io.ktor.network.selector/Selectable) // io.ktor.network.selector/SelectorManager.notifyClosed|notifyClosed(io.ktor.network.selector.Selectable){}[0]
abstract suspend fun select(io.ktor.network.selector/Selectable, io.ktor.network.selector/SelectInterest) // io.ktor.network.selector/SelectorManager.select|select(io.ktor.network.selector.Selectable;io.ktor.network.selector.SelectInterest){}[0]
@@ -103,10 +99,6 @@ final class io.ktor.network.selector/ClosedChannelCancellationException : kotlin
constructor <init>() // io.ktor.network.selector/ClosedChannelCancellationException.<init>|<init>(){}[0]
}

final class io.ktor.network.selector/SocketError : kotlin/IllegalStateException { // io.ktor.network.selector/SocketError|null[0]
constructor <init>() // io.ktor.network.selector/SocketError.<init>|<init>(){}[0]
}

final class io.ktor.network.sockets/Connection { // io.ktor.network.sockets/Connection|null[0]
constructor <init>(io.ktor.network.sockets/Socket, io.ktor.utils.io/ByteReadChannel, io.ktor.utils.io/ByteWriteChannel) // io.ktor.network.sockets/Connection.<init>|<init>(io.ktor.network.sockets.Socket;io.ktor.utils.io.ByteReadChannel;io.ktor.utils.io.ByteWriteChannel){}[0]

@@ -284,3 +276,17 @@ final fun <#A: io.ktor.network.sockets/Configurable<#A, *>> (#A).io.ktor.network
final fun io.ktor.network.selector/SelectorManager(kotlin.coroutines/CoroutineContext = ...): io.ktor.network.selector/SelectorManager // io.ktor.network.selector/SelectorManager|SelectorManager(kotlin.coroutines.CoroutineContext){}[0]
final fun io.ktor.network.sockets/aSocket(io.ktor.network.selector/SelectorManager): io.ktor.network.sockets/SocketBuilder // io.ktor.network.sockets/aSocket|aSocket(io.ktor.network.selector.SelectorManager){}[0]
final suspend fun (io.ktor.network.sockets/ASocket).io.ktor.network.sockets/awaitClosed() // io.ktor.network.sockets/awaitClosed|awaitClosed@io.ktor.network.sockets.ASocket(){}[0]

// Targets: [native]
abstract interface io.ktor.network.selector/Selectable { // io.ktor.network.selector/Selectable|null[0]
abstract val descriptor // io.ktor.network.selector/Selectable.descriptor|{}descriptor[0]
abstract fun <get-descriptor>(): kotlin/Int // io.ktor.network.selector/Selectable.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
}

// Targets: [native]
final class io.ktor.network.selector/SocketError : kotlin/IllegalStateException { // io.ktor.network.selector/SocketError|null[0]
constructor <init>() // io.ktor.network.selector/SocketError.<init>|<init>(){}[0]
}

// Targets: [js, wasmJs]
abstract interface io.ktor.network.selector/Selectable // io.ktor.network.selector/Selectable|null[0]
4 changes: 2 additions & 2 deletions ktor-network/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -10,13 +10,13 @@ kotlin {
}

sourceSets {
jvmAndPosixMain {
commonMain {
dependencies {
api(project(":ktor-utils"))
}
}

jvmAndPosixTest {
commonTest {
dependencies {
api(project(":ktor-test-dispatcher"))
}
Original file line number Diff line number Diff line change
@@ -11,7 +11,6 @@ import kotlin.coroutines.*
/**
* Creates the selector manager for current platform.
*/
@Suppress("FunctionName")
public expect fun SelectorManager(
dispatcher: CoroutineContext = EmptyCoroutineContext
): SelectorManager
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.network.sockets

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.network.sockets
32 changes: 32 additions & 0 deletions ktor-network/common/src/io/ktor/network/sockets/SocketEngine.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.network.sockets

import io.ktor.network.selector.*

internal expect suspend fun tcpConnect(
selector: SelectorManager,
remoteAddress: SocketAddress,
socketOptions: SocketOptions.TCPClientSocketOptions
): Socket

internal expect suspend fun tcpBind(
selector: SelectorManager,
localAddress: SocketAddress?,
socketOptions: SocketOptions.AcceptorOptions
): ServerSocket

internal expect suspend fun udpConnect(
selector: SelectorManager,
remoteAddress: SocketAddress,
localAddress: SocketAddress?,
options: SocketOptions.UDPSocketOptions
): ConnectedDatagramSocket

internal expect suspend fun udpBind(
selector: SelectorManager,
localAddress: SocketAddress?,
options: SocketOptions.UDPSocketOptions
): BoundDatagramSocket
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

package io.ktor.network.sockets

internal const val INFINITE_TIMEOUT_MS = Long.MAX_VALUE
private const val INFINITE_TIMEOUT_MS = Long.MAX_VALUE

/**
* Socket options builder
@@ -29,7 +29,7 @@ public sealed class SocketOptions(
}
}

internal fun acceptor(): AcceptorOptions {
internal fun tcpAccept(): AcceptorOptions {
return AcceptorOptions(HashMap(customOptions)).apply {
copyCommon(this@SocketOptions)
}
@@ -112,7 +112,7 @@ public sealed class SocketOptions(
}
}

internal fun tcp(): TCPClientSocketOptions {
internal fun tcpConnect(): TCPClientSocketOptions {
return TCPClientSocketOptions(HashMap(customOptions)).apply {
copyCommon(this@PeerSocketOptions)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.network.sockets

Original file line number Diff line number Diff line change
@@ -37,13 +37,13 @@ public class TcpSocketBuilder internal constructor(
public suspend fun connect(
remoteAddress: SocketAddress,
configure: SocketOptions.TCPClientSocketOptions.() -> Unit = {}
): Socket = connect(selector, remoteAddress, options.tcp().apply(configure))
): Socket = tcpConnect(selector, remoteAddress, options.tcpConnect().apply(configure))

/**
* Bind server socket to listen to [localAddress].
*/
public suspend fun bind(
localAddress: SocketAddress? = null,
configure: SocketOptions.AcceptorOptions.() -> Unit = {}
): ServerSocket = bind(selector, localAddress, options.acceptor().apply(configure))
): ServerSocket = tcpBind(selector, localAddress, options.tcpAccept().apply(configure))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.network.sockets

Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ public class UDPSocketBuilder internal constructor(
public suspend fun bind(
localAddress: SocketAddress? = null,
configure: SocketOptions.UDPSocketOptions.() -> Unit = {}
): BoundDatagramSocket = bindUDP(selector, localAddress, options.udp().apply(configure))
): BoundDatagramSocket = udpBind(selector, localAddress, options.udp().apply(configure))

/**
* Create a datagram socket to listen datagrams at [localAddress] and set to [remoteAddress].
@@ -28,18 +28,5 @@ public class UDPSocketBuilder internal constructor(
remoteAddress: SocketAddress,
localAddress: SocketAddress? = null,
configure: SocketOptions.UDPSocketOptions.() -> Unit = {}
): ConnectedDatagramSocket = connectUDP(selector, remoteAddress, localAddress, options.udp().apply(configure))
): ConnectedDatagramSocket = udpConnect(selector, remoteAddress, localAddress, options.udp().apply(configure))
}

internal expect fun connectUDP(
selector: SelectorManager,
remoteAddress: SocketAddress,
localAddress: SocketAddress?,
options: SocketOptions.UDPSocketOptions
): ConnectedDatagramSocket

internal expect fun bindUDP(
selector: SelectorManager,
localAddress: SocketAddress?,
options: SocketOptions.UDPSocketOptions
): BoundDatagramSocket
Original file line number Diff line number Diff line change
@@ -62,48 +62,49 @@ class TCPSocketTest {
if (!supportsUnixDomainSockets()) return@testSockets

val socketPath = createTempFilePath("ktor-echo-test")
try {
val tcp = aSocket(selector).tcp()
val server = tcp.bind(UnixSocketAddress(socketPath))

val tcp = aSocket(selector).tcp()
val server = tcp.bind(UnixSocketAddress(socketPath))
val serverConnectionPromise = async {
server.accept()
}

val serverConnectionPromise = async {
server.accept()
}
val clientConnection = tcp.connect(UnixSocketAddress(socketPath))
val serverConnection = serverConnectionPromise.await()

val clientConnection = tcp.connect(UnixSocketAddress(socketPath))
val serverConnection = serverConnectionPromise.await()
val clientOutput = clientConnection.openWriteChannel()
try {
clientOutput.writeStringUtf8("Hello, world\n")
clientOutput.flush()
} finally {
clientOutput.flushAndClose()
}

val clientOutput = clientConnection.openWriteChannel()
try {
clientOutput.writeStringUtf8("Hello, world\n")
clientOutput.flush()
} finally {
clientOutput.flushAndClose()
}
val serverInput = serverConnection.openReadChannel()
val message = serverInput.readUTF8Line()
assertEquals("Hello, world", message)

val serverInput = serverConnection.openReadChannel()
val message = serverInput.readUTF8Line()
assertEquals("Hello, world", message)
val serverOutput = serverConnection.openWriteChannel()
try {
serverOutput.writeStringUtf8("Hello From Server\n")
serverOutput.flush()

val serverOutput = serverConnection.openWriteChannel()
try {
serverOutput.writeStringUtf8("Hello From Server\n")
serverOutput.flush()
val clientInput = clientConnection.openReadChannel()
val echo = clientInput.readUTF8Line()

val clientInput = clientConnection.openReadChannel()
val echo = clientInput.readUTF8Line()
assertEquals("Hello From Server", echo)
} finally {
serverOutput.flushAndClose()
}

assertEquals("Hello From Server", echo)
serverConnection.close()
clientConnection.close()

server.close()
} finally {
serverOutput.flushAndClose()
removeFile(socketPath)
}

serverConnection.close()
clientConnection.close()

server.close()

removeFile(socketPath)
}

@Test
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.network.sockets.tests

import io.ktor.network.selector.*
import io.ktor.test.dispatcher.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
import kotlinx.io.files.*
import kotlin.time.*
import kotlin.time.Duration.Companion.minutes
import kotlin.uuid.*

internal fun testSockets(
timeout: Duration = 1.minutes,
block: suspend CoroutineScope.(SelectorManager) -> Unit
): TestResult = runTestWithRealTime(timeout = timeout) {
SelectorManager().use { selector ->
block(selector)
}
}

internal expect fun Any.supportsUnixDomainSockets(): Boolean

@OptIn(ExperimentalUuidApi::class)
internal fun createTempFilePath(basename: String): String {
return Path(SystemTemporaryDirectory, "$basename-${Uuid.random()}").toString()
}

internal fun removeFile(path: String) {
SystemFileSystem.delete(Path(path), mustExist = false)
}
5 changes: 5 additions & 0 deletions ktor-network/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
# Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
#
target.js.browser=false
target.wasmJs.browser=false

This file was deleted.

Loading