This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-05-06
Channels
- # announcements (37)
- # babashka (17)
- # beginners (20)
- # calva (2)
- # clj-kondo (15)
- # cljs-dev (1)
- # clojure (6)
- # clojure-austin (2)
- # clojure-china (3)
- # clojure-europe (27)
- # clojure-korea (1)
- # clojure-nl (1)
- # clojure-norway (18)
- # clojurescript (13)
- # conjure (3)
- # datomic (31)
- # events (3)
- # honeysql (14)
- # jobs-discuss (33)
- # leiningen (4)
- # lsp (57)
- # membrane (3)
- # missionary (5)
- # off-topic (1)
- # releases (3)
- # shadow-cljs (18)
- # slack-help (2)
- # specter (2)
- # yamlscript (10)
Question for folks who have experience with undertow:
Problem: If I manually close a channel, I notice that neither on-close-message
or on-error
callbacks are called.
For example:
(def id-atom (atom 0))
(defn ws-handler [_]
(let [id (swap! id-atom inc)]
{:undertow/websocket
{:on-open (fn [{:keys [channel]}]
(println (format " [%s] online!" id))
(ws/send (format " [%s] ok" id) channel))
:on-message (fn [{:keys [channel data]}]
(if (= "break" (str/trim data))
(do
(println (format " [%s] about to break!" id))
(.close channel))
(do
(println (format " [%s] received %s" id data))
(ws/send (format " [%s] received %s" id data) channel))))
:on-close-message (fn [_]
(println (format " [%s] closed!" id)))
:on-error (fn [_]
(println (format " [%s] error! " id)))}}))
If I send the break
command in this websocket, the client will disconnect, but on-close-message
or on-error
will never get called.
Is this expected? Previously I thought I could rely on on-close-message
being called, so I could always do some kind of cleanup in that callback. But writing this example makes me a bit confused: are there times when websocket connections can close, but the callback won't run?
I made a quick repro project here: https://github.com/stopachka/manual-close-error/tree/main
Thoughts much appreciated!don't call .close on the channel, that likely closes the tcp connection and doesn't cleanly shutdown the websocket connection
part of the websocket protocol is there is an explicit close message that can contain an information number code about why the socket is being closed
on-close-message handles those messages, calling .close on the channel likely closes at least the server sending side of the tcp connection (maybe both sides?), and the client might respond to that by deciding the websocket is broken and not bothering to do a clean shutdown of the connection
you can see here(https://github.com/ring-clojure/ring/blob/master/ring-websocket-protocols/src/ring/websocket/protocols.clj#L40) the relatively new ring spec for websockets includes a close function that takes the reason code for sending to the client, but it looks like the non-standard websocket extension the luminus undertow ring adapter provides doesn't seem to have such a thing
you could try calling sendClose on the channel instead https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/websockets/core/WebSocketChannel.java#L372-L388