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

WebSocketConfigurer#onClose not called #3111

Closed
U1F984 opened this issue Aug 28, 2023 · 1 comment
Closed

WebSocketConfigurer#onClose not called #3111

U1F984 opened this issue Aug 28, 2023 · 1 comment

Comments

@U1F984
Copy link
Contributor

U1F984 commented Aug 28, 2023

When a client disconnects in an unclean fashion (e.g. process crashes, connection is dropped) the onClose is never called.

Jooby Version: 3.0.1 (with undertow)

Reproduction example:

Server

import io.jooby.Jooby

class App : Jooby() {
    init {
        ws("/foo") { ctx, configurer ->
            configurer.onConnect { ws -> log.info("Connected") }
            configurer.onError { ws, err -> log.info("Error", err) }
            configurer.onClose { ws, closeStatus -> log.info("Disconnected") }
        }
    }
}

fun main() {
    Jooby.runApp(emptyArray(), ::App)
}

Client (using com.squareup.okhttp:okhttp:2.7.5, com.squareup.okhttp:okhttp-ws:2.7.5)

import com.squareup.okhttp.OkHttpClient
import com.squareup.okhttp.Request
import com.squareup.okhttp.Response
import com.squareup.okhttp.ResponseBody
import com.squareup.okhttp.ws.WebSocket
import com.squareup.okhttp.ws.WebSocketCall
import com.squareup.okhttp.ws.WebSocketListener
import okio.Buffer
import java.io.IOException
import java.util.concurrent.TimeUnit

fun main() {
    val client = OkHttpClient()

    makeCall(client)

    client.dispatcher.executorService.shutdown()
    client.dispatcher.executorService.awaitTermination(1, TimeUnit.SECONDS)
}

private fun makeCall(client: OkHttpClient) {
    val ws = WebSocketCall.create(client, Request.Builder().url("http://localhost:8080/foo").build())
    ws.enqueue(object : WebSocketListener {
        override fun onOpen(webSocket: WebSocket, response: Response) {
        }

        override fun onFailure(e: IOException, response: Response?) {

        }

        override fun onMessage(message: ResponseBody) {
        }

        override fun onPong(payload: Buffer) {

        }

        override fun onClose(code: Int, reason: String?) {

        }
    })
}

Start server, start client, wait for client to exit and observe that only Connected is logged. Issue seems to be that io.jooby.internal.undertow.UndertowWebSocket#onCloseMessage is called, but channel.isOpen() is already false so close handler is not invoked.

@jknack
Copy link
Member

jknack commented Aug 28, 2023

Thank you. Fixed in 3.0.5 (will release a bit). The bug was fixed for undertow and jetty. Netty doesn't fire the disconnect error.

@jknack jknack closed this as completed Aug 28, 2023
jknack added a commit that referenced this issue Aug 28, 2023
- fixed for undertow and jetty.
- netty doesn't fire the client disconnected event
- fix #3111
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants