diff options
author | Loïc Hoguin <[email protected]> | 2025-04-11 14:34:51 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2025-04-11 14:34:51 +0200 |
commit | eb808a3f8bbd97d2a2ea0114b43b708a17b44066 (patch) | |
tree | fc142e5b11792af4f84d8634d9a8809f32344634 /docs/en/gun/2.2/guide/websocket.asciidoc | |
parent | 25e93c91878b7f8536764b06d2cb72020031acd1 (diff) | |
download | ninenines.eu-master.tar.gz ninenines.eu-master.tar.bz2 ninenines.eu-master.zip |
Diffstat (limited to 'docs/en/gun/2.2/guide/websocket.asciidoc')
-rw-r--r-- | docs/en/gun/2.2/guide/websocket.asciidoc | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/docs/en/gun/2.2/guide/websocket.asciidoc b/docs/en/gun/2.2/guide/websocket.asciidoc new file mode 100644 index 00000000..31b014bf --- /dev/null +++ b/docs/en/gun/2.2/guide/websocket.asciidoc @@ -0,0 +1,141 @@ +[[websocket]] +== Websocket + +This chapter describes how to use the Gun client for +communicating with a Websocket server. + +// @todo recovering from connection failure, reconnecting to Websocket etc. + +=== HTTP upgrade + +Websocket is a protocol built on top of HTTP. To use Websocket, +you must first request for the connection to be upgraded. Only +HTTP/1.1 connections can be upgraded to Websocket, so you might +need to restrict the protocol to HTTP/1.1 if you are planning +to use Websocket over TLS. + +You must use the `gun:ws_upgrade/2,3,4` function to upgrade +to Websocket. This function can be called anytime after connection, +so you can send HTTP requests before upgrading to Websocket. + +.Upgrade to Websocket +[source,erlang] +---- +gun:ws_upgrade(ConnPid, "/websocket"). +---- + +Gun will set all the necessary headers for performing the +Websocket upgrade, but you can specify additional headers +if needed. For example you can authenticate. + +.Upgrade to Websocket using HTTP authentication +[source,erlang] +---- +gun:ws_upgrade(ConnPid, "/websocket", [ + {<<"authorization">>, "Basic dXNlcm5hbWU6cGFzc3dvcmQ="} +]). +---- + +You can pass the Websocket options as part of the `gun:open/2,3` +call when opening the connection, or using the `gun:ws_upgrade/4`. +The fourth argument is those same options. + +Gun can negotiate the protocol to be used for the Websocket +connection. The `protocols` option can be given with a list +of protocols accepted and the corresponding handler module. +Note that the interface for handler modules is currently +undocumented and must be set to `gun_ws_h`. + +.Upgrade to Websocket with protocol negotiation +[source,erlang] +---- +StreamRef = gun:ws_upgrade(ConnPid, "/websocket", [] + #{protocols => [{<<"xmpp">>, gun_ws_h}]}). +---- + +The upgrade will fail if the server cannot satisfy the +protocol negotiation. + +When the upgrade succeeds, a `gun_upgrade` message is sent. +If the server does not understand Websocket or refused the +upgrade, a `gun_response` message is sent. If Gun couldn't +perform the upgrade due to an error (for example attempting +to upgrade to Websocket on an HTTP/1.0 connection) then a +`gun_error` message is sent. + +When the server does not understand Websocket, it may send +a meaningful response which should be processed. In the +following example we however ignore it: + +[source,erlang] +---- +receive + {gun_upgrade, ConnPid, StreamRef, [<<"websocket">>], Headers} -> + upgrade_success(ConnPid, StreamRef); + {gun_response, ConnPid, _, _, Status, Headers} -> + exit({ws_upgrade_failed, Status, Headers}); + {gun_error, ConnPid, StreamRef, Reason} -> + exit({ws_upgrade_failed, Reason}) + %% More clauses here as needed. +after 1000 -> + exit(timeout) +end. +---- + +=== Sending data + +Once the Websocket upgrade has completed successfully, you no +longer have access to functions for performing requests. You +can only send and receive Websocket messages. + +Use `gun:ws_send/3` to send messages to the server. + +.Send a text frame +[source,erlang] +---- +gun:ws_send(ConnPid, StreamRef, {text, "Hello!"}). +---- + +.Send a text frame, a binary frame and then close the connection +[source,erlang] +---- +gun:ws_send(ConnPid, StreamRef, [ + {text, "Hello!"}, + {binary, BinaryValue}, + close +]). +---- + +Note that if you send a close frame, Gun will close the connection +cleanly but may attempt to reconnect afterwards depending on the +`retry` configuration. + +=== Receiving data + +Gun sends an Erlang message to the owner process for every +Websocket message it receives. + +[source,erlang] +---- +receive + {gun_ws, ConnPid, StreamRef, Frame} -> + handle_frame(ConnPid, StreamRef, Frame) +end. +---- + +=== Automatic reconnect gotchas + +It is recommended to disable automatic reconnect when +Websocket is used because Gun cannot automatically upgrade +to Websocket on reconnect, and so an undetected disconnect +may lead to many error messages from Gun. + +This can be done by setting the `retry` option to `0` +when opening a connection: + +[source,erlang] +---- +{ok, ConnPid} = gun:open("localhost", 12345, #{ + retry ⇒ 0 +}). +---- |