Question

I have implemented a simple appmod that handle WebSockets and echo back the messages. But how do I handle an ws.close(); from the JavaScript client? I have tried with the code below, but handle_message({close, Reason}) is never called and ws.onclose = function(evt) {} is never executed on the JavaScript client.

When I use the same JavaScript client code interacting with a node.js websocket, the client receives an onclose event immediately after ws.close();.

Here is the code for my simple appmod:

-module(mywebsocket).
-export([handle_message/1]).

handle_message({text, Message}) ->
    {reply, {text, <<Message/binary>>}};

handle_message({close, Reason}) ->
    io:format("User closed websocket.~n", []),
    {close, normal}.
Était-ce utile?

La solution

Updated answer:

As of github commit 16834c, which will eventually be part of Yaws 1.93, Yaws passes a new callback to your WebSockets callback module when the client sends a close message. The callback is:

{close, Status, Reason}

where Status is either the close status sent by the client, or the numerical value 1000 (specified by RFC 6455 for a normal close) if the client didn't include a status value. Reason is a binary holding any optional reason string passed from the client; it will be an empty binary if the client sent no reason.

Your callback handler for a close message MUST return {close, CloseReason} where CloseReason is either the atom normal for a normal close (which results in the status code 1000 being returned to the client) or another legal numerical status code allowed by RFC 6455. Note that CloseReason is unrelated to any Reason value passed by the client. Technically CloseReason can also be any other Erlang term, in which case Yaws returns status 1000 and passes the term to erlang:exit/1 to exit the Erlang process handling the web socket, but based on RFC 6455 we suggest simply returning the atom normal for CloseReason in all cases.

Original answer, obsoleted by Yaws github commit 16834c:

Yaws never passes a {close, Reason} message to your callback module. Rather, {close, Reason} is a valid return value from handle_message/1 should your callback module decide it wants to close the ws socket.

I modified the websockets_example.yaws file shipped with Yaws (version 1.92) to call this._ws.close() in the client if the user enters the "bye" message on the web page, and added an alert to the _onclose function to show that the onclose event is triggered. In this case the alert occurred, I believe because the "bye" message causes the server to close the ws socket explicitly. But I then modified the example to call this._ws.close() in the client no matter what message the user enters, and in that case no alert for onclose occurred. In this case, a check with lsof showed the ws connection from the browser to Yaws was still present.

So, for now I believe you've hit a bug where the Yaws websockets support isn't detecting the client close and closing its end. I'll see if I can fix it.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top