diff --git a/CHANGELOG.md b/CHANGELOG.md index 48edbd27042..8799b74afa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ * New function `UnifiedRequester#createStandardWebsocketFlow` without `checkReconnection` arg * Server: * Now it is possible to filter data in `Route#includeWebsocketHandling` - * Callback in `Route#includeWebsocketHandling` is `suspend` since now + * Callback in `Route#includeWebsocketHandling` and dependent methods is `suspend` since now + * Add `URLProtocol` support in `Route#includeWebsocketHandling` and dependent methods ## 0.9.9 diff --git a/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/FlowsWebsockets.kt b/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/FlowsWebsockets.kt index 567d87e5b01..048c92dae3d 100644 --- a/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/FlowsWebsockets.kt +++ b/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/FlowsWebsockets.kt @@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.ktor.common.* import io.ktor.client.HttpClient import io.ktor.client.features.websocket.ws +import io.ktor.client.request.HttpRequestBuilder import io.ktor.http.cio.websocket.Frame import io.ktor.http.cio.websocket.readBytes import kotlinx.coroutines.flow.Flow @@ -17,6 +18,7 @@ import kotlinx.serialization.DeserializationStrategy inline fun HttpClient.createStandardWebsocketFlow( url: String, crossinline checkReconnection: (Throwable?) -> Boolean = { true }, + noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}, crossinline conversation: suspend (StandardKtorSerialInputData) -> T ): Flow { val correctedUrl = url.asCorrectWebSocketUrl @@ -26,7 +28,7 @@ inline fun HttpClient.createStandardWebsocketFlow( do { val reconnect = try { safely { - ws(correctedUrl) { + ws(correctedUrl, requestBuilder) { for (received in incoming) { when (received) { is Frame.Binary -> producerScope.send(conversation(received.readBytes())) @@ -65,10 +67,12 @@ inline fun HttpClient.createStandardWebsocketFlow( url: String, crossinline checkReconnection: (Throwable?) -> Boolean = { true }, deserializer: DeserializationStrategy, - serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat + serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat, + noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}, ) = createStandardWebsocketFlow( url, - checkReconnection + checkReconnection, + requestBuilder ) { serialFormat.decodeDefault(deserializer, it) } diff --git a/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/StandardHttpClientGetPost.kt b/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/StandardHttpClientGetPost.kt index dc3d88a235f..c7922e312ac 100644 --- a/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/StandardHttpClientGetPost.kt +++ b/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/StandardHttpClientGetPost.kt @@ -86,13 +86,15 @@ class UnifiedRequester( fun createStandardWebsocketFlow( url: String, checkReconnection: (Throwable?) -> Boolean, - deserializer: DeserializationStrategy - ) = client.createStandardWebsocketFlow(url, checkReconnection, deserializer, serialFormat) + deserializer: DeserializationStrategy, + requestBuilder: HttpRequestBuilder.() -> Unit = {}, + ) = client.createStandardWebsocketFlow(url, checkReconnection, deserializer, serialFormat, requestBuilder) fun createStandardWebsocketFlow( url: String, - deserializer: DeserializationStrategy - ) = createStandardWebsocketFlow(url, { true }, deserializer) + deserializer: DeserializationStrategy, + requestBuilder: HttpRequestBuilder.() -> Unit = {}, + ) = createStandardWebsocketFlow(url, { true }, deserializer, requestBuilder) } val defaultRequester = UnifiedRequester() diff --git a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/FlowsWebsocket.kt b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/FlowsWebsocket.kt index 0a47a932fc4..01aaaf2952f 100644 --- a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/FlowsWebsocket.kt +++ b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/FlowsWebsocket.kt @@ -4,23 +4,24 @@ import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.ktor.common.* import io.ktor.application.featureOrNull import io.ktor.application.install +import io.ktor.http.URLProtocol import io.ktor.http.cio.websocket.* import io.ktor.routing.Route import io.ktor.routing.application -import io.ktor.websocket.WebSocketServerSession -import io.ktor.websocket.webSocket +import io.ktor.websocket.* import kotlinx.coroutines.flow.Flow import kotlinx.serialization.SerializationStrategy fun Route.includeWebsocketHandling( suburl: String, flow: Flow, + protocol: URLProtocol = URLProtocol.WS, converter: suspend WebSocketServerSession.(T) -> StandardKtorSerialInputData? ) { application.apply { featureOrNull(io.ktor.websocket.WebSockets) ?: install(io.ktor.websocket.WebSockets) } - webSocket(suburl) { + webSocket(suburl, protocol.name) { safely { flow.collect { converter(it) ?.let { data -> @@ -36,10 +37,12 @@ fun Route.includeWebsocketHandling( flow: Flow, serializer: SerializationStrategy, serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat, + protocol: URLProtocol = URLProtocol.WS, filter: (suspend WebSocketServerSession.(T) -> Boolean)? = null ) = includeWebsocketHandling( suburl, flow, + protocol, converter = if (filter == null) { { serialFormat.encodeDefault(serializer, it) diff --git a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/ServerRoutingShortcuts.kt b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/ServerRoutingShortcuts.kt index eec3976f64e..f2c06bc5e52 100644 --- a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/ServerRoutingShortcuts.kt +++ b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/ServerRoutingShortcuts.kt @@ -5,8 +5,7 @@ import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.ktor.common.* import io.ktor.application.ApplicationCall import io.ktor.application.call -import io.ktor.http.ContentType -import io.ktor.http.HttpStatusCode +import io.ktor.http.* import io.ktor.http.content.PartData import io.ktor.http.content.forEachPart import io.ktor.request.receive @@ -32,8 +31,9 @@ class UnifiedRouter( suburl: String, flow: Flow, serializer: SerializationStrategy, + protocol: URLProtocol = URLProtocol.WS, filter: (suspend WebSocketServerSession.(T) -> Boolean)? = null - ) = includeWebsocketHandling(suburl, flow, serializer, serialFormat, filter) + ) = includeWebsocketHandling(suburl, flow, serializer, serialFormat, protocol, filter) suspend fun PipelineContext<*, ApplicationCall>.unianswer( answerSerializer: SerializationStrategy,