How do I handle a WebSocket close from the client in Yaws?

不问归期 提交于 2019-12-08 03:47:40

问题


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}.

回答1:


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.



来源:https://stackoverflow.com/questions/9222786/how-do-i-handle-a-websocket-close-from-the-client-in-yaws

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!