diff options
Diffstat (limited to 'docs/en/cowboy/2.0/guide/ws_handlers/index.html')
-rw-r--r-- | docs/en/cowboy/2.0/guide/ws_handlers/index.html | 533 |
1 files changed, 268 insertions, 265 deletions
diff --git a/docs/en/cowboy/2.0/guide/ws_handlers/index.html b/docs/en/cowboy/2.0/guide/ws_handlers/index.html index 7ec685bf..334bb049 100644 --- a/docs/en/cowboy/2.0/guide/ws_handlers/index.html +++ b/docs/en/cowboy/2.0/guide/ws_handlers/index.html @@ -7,7 +7,7 @@ <meta name="description" content=""> <meta name="author" content="Loïc Hoguin based on a design from (Soft10) Pol Cámara"> - <meta name="generator" content="Hugo 0.17" /> + <meta name="generator" content="Hugo 0.26" /> <title>Nine Nines: Websocket handlers</title> @@ -67,276 +67,279 @@ <h1 class="lined-header"><span>Websocket handlers</span></h1> -<div class="paragraph"><p>Websocket handlers provide an interface for upgrading HTTP/1.1
-connections to Websocket and sending or receiving frames on
-the Websocket connection.</p></div>
-<div class="paragraph"><p>As Websocket connections are established through the HTTP/1.1
-upgrade mechanism, Websocket handlers need to be able to first
-receive the HTTP request for the upgrade, before switching to
-Websocket and taking over the connection. They can then receive
-or send Websocket frames, handle incoming Erlang messages or
-close the connection.</p></div>
-<div class="sect1">
-<h2 id="_upgrade">Upgrade</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>The <code>init/2</code> callback is called when the request is received.
-To establish a Websocket connection, you must switch to the
-<code>cowboy_websocket</code> module:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>Cowboy will perform the Websocket handshake immediately. Note
-that the handshake will fail if the client did not request an
-upgrade to Websocket.</p></div>
-<div class="paragraph"><p>The Req object becomes unavailable after this function returns.
-Any information required for proper execution of the Websocket
-handler must be saved in the state.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_subprotocol">Subprotocol</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>The client may provide a list of Websocket subprotocols it
-supports in the sec-websocket-protocol header. The server <strong>must</strong>
-select one of them and send it back to the client or the
-handshake will fail.</p></div>
-<div class="paragraph"><p>For example, a client could understand both STOMP and MQTT over
-Websocket, and provide the header:</p></div>
-<div class="listingblock">
-<div class="content">
-<pre><code>sec-websocket-protocol: v12.stomp, mqtt</code></pre>
-</div></div>
-<div class="paragraph"><p>If the server only understands MQTT it can return:</p></div>
-<div class="listingblock">
-<div class="content">
-<pre><code>sec-websocket-protocol: mqtt</code></pre>
-</div></div>
-<div class="paragraph"><p>This selection must be done in <code>init/2</code>. An example usage could
-be:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">cowboy_req:parse_header</span></span>(<span style="color: #990000"><<</span><span style="color: #FF0000">"sec-websocket-protocol"</span><span style="color: #990000">>></span>, <span style="color: #009900">Req</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span>
- <span style="color: #000080">undefined</span> <span style="color: #990000">-></span>
- {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>};
- <span style="color: #009900">Subprotocols</span> <span style="color: #990000">-></span>
- <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">lists:keymember</span></span>(<span style="color: #990000"><<</span><span style="color: #FF0000">"mqtt"</span><span style="color: #990000">>></span>, <span style="color: #993399">1</span>, <span style="color: #009900">Subprotocols</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span>
- <span style="color: #000080">true</span> <span style="color: #990000">-></span>
- <span style="color: #009900">Req2</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">cowboy_req:set_resp_header</span></span>(<span style="color: #990000"><<</span><span style="color: #FF0000">"sec-websocket-protocol"</span><span style="color: #990000">>></span>,
- <span style="color: #990000"><<</span><span style="color: #FF0000">"mqtt"</span><span style="color: #990000">>></span>, <span style="color: #009900">Req</span>),
- {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req2</span>, <span style="color: #009900">State</span>};
- <span style="color: #000080">false</span> <span style="color: #990000">-></span>
- {<span style="color: #FF6600">stop</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}
- <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
- <span style="font-weight: bold"><span style="color: #0000FF">end</span></span><span style="color: #990000">.</span></tt></pre></div></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_post_upgrade_initialization">Post-upgrade initialization</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Cowboy has separate processes for handling the connection
-and requests. Because Websocket takes over the connection,
-the Websocket protocol handling occurs in a different
-process than the request handling.</p></div>
-<div class="paragraph"><p>This is reflected in the different callbacks Websocket
-handlers have. The <code>init/2</code> callback is called from the
-temporary request process and the <code>websocket_</code> callbacks
-from the connection process.</p></div>
-<div class="paragraph"><p>This means that some initialization cannot be done from
-<code>init/2</code>. Anything that would require the current pid,
-or be tied to the current pid, will not work as intended.
-The optional <code>websocket_init/1</code> can be used instead:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- <span style="font-weight: bold"><span style="color: #000000">erlang:start_timer</span></span>(<span style="color: #993399">1000</span>, <span style="font-weight: bold"><span style="color: #000080">self</span></span>(), <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>),
- {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>All Websocket callbacks share the same return values. This
-means that we can send frames to the client right after
-the upgrade:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_receiving_frames">Receiving frames</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Cowboy will call <code>websocket_handle/2</code> whenever a text, binary,
-ping or pong frame arrives from the client.</p></div>
-<div class="paragraph"><p>The handler can handle or ignore the frames. It can also
-send frames back to the client or stop the connection.</p></div>
-<div class="paragraph"><p>The following snippet echoes back any text frame received and
-ignores all others:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">Frame</span> <span style="color: #990000">=</span> {<span style="color: #FF6600">text</span>, <span style="color: #990000">_</span>}, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">reply</span>, <span style="color: #009900">Frame</span>, <span style="color: #009900">State</span>};
-<span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">_Frame</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>Note that ping and pong frames require no action from the
-handler as Cowboy will automatically reply to ping frames.
-They are provided for informative purposes only.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_receiving_erlang_messages">Receiving Erlang messages</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Cowboy will call <code>websocket_info/2</code> whenever an Erlang message
-arrives.</p></div>
-<div class="paragraph"><p>The handler can handle or ignore the messages. It can also
-send frames to the client or stop the connection.</p></div>
-<div class="paragraph"><p>The following snippet forwards log messages to the client
-and ignores all others:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>({<span style="font-weight: bold"><span style="color: #000080">log</span></span>, <span style="color: #009900">Text</span>}, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #009900">Text</span>}, <span style="color: #009900">State</span>};
-<span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_sending_frames">Sending frames</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>All <code>websocket_</code> callbacks share return values. They may
-send zero, one or many frames to the client.</p></div>
-<div class="paragraph"><p>To send nothing, just return an ok tuple:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>To send one frame, return a reply tuple with the frame to send:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>You can send frames of any type: text, binary, ping, pong
-or close frames.</p></div>
-<div class="paragraph"><p>To send many frames at once, return a reply tuple with the
-list of frames to send:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">reply</span>, [
- {<span style="color: #FF6600">text</span>, <span style="color: #FF0000">"Hello"</span>},
- {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"world!"</span><span style="color: #990000">>></span>},
- {<span style="font-weight: bold"><span style="color: #000080">binary</span></span>, <span style="color: #990000"><<</span><span style="color: #993399">0</span><span style="color: #990000">:</span><span style="color: #993399">8000</span><span style="color: #990000">>></span>}
- ], <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>They are sent in the given order.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_keeping_the_connection_alive">Keeping the connection alive</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Cowboy will automatically respond to ping frames sent by
-the client. They are still forwarded to the handler for
-informative purposes, but no further action is required.</p></div>
-<div class="paragraph"><p>Cowboy does not send ping frames itself. The handler can
-do it if required. A better solution in most cases is to
-let the client handle pings. Doing it from the handler
-would imply having an additional timer per connection and
-this can be a considerable cost for servers that need to
-handle large numbers of connections.</p></div>
-<div class="paragraph"><p>Cowboy can be configured to close idle connections
-automatically. It is highly recommended to configure
-a timeout here, to avoid having processes linger longer
-than needed.</p></div>
-<div class="paragraph"><p>The <code>init/2</code> callback can set the timeout to be used
-for the connection. For example, this would make Cowboy
-close connections idle for more than 30 seconds:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>, #{
- <span style="color: #0000FF">idle_timeout</span> <span style="color: #990000">=></span> <span style="color: #993399">30000</span>}}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>This value cannot be changed once it is set. It defaults to
-<code>60000</code>.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_saving_memory">Saving memory</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>The Websocket connection process can be set to hibernate
-after the callback returns.</p></div>
-<div class="paragraph"><p>Simply add an <code>hibernate</code> field to the ok or reply tuples:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span>
-
-<span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">_Frame</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span>
-
-<span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>It is highly recommended to write your handlers with
-hibernate enabled, as this allows to greatly reduce the
-memory usage. Do note however that an increase in the
-CPU usage or latency can be observed instead, in particular
-for the more busy connections.</p></div>
-</div>
-</div>
-<div class="sect1">
-<h2 id="_closing_the_connection">Closing the connection</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>The connection can be closed at any time, either by telling
-Cowboy to stop it or by sending a close frame.</p></div>
-<div class="paragraph"><p>To tell Cowboy to close the connection, use a stop tuple:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span>
- {<span style="color: #FF6600">stop</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>Sending a <code>close</code> frame will immediately initiate the closing
-of the Websocket connection. Note that when sending a list of
-frames that include a close frame, any frame found after the
-close frame will not be sent.</p></div>
-</div>
-</div>
+<div class="paragraph"><p>Websocket handlers provide an interface for upgrading HTTP/1.1 +connections to Websocket and sending or receiving frames on +the Websocket connection.</p></div> +<div class="paragraph"><p>As Websocket connections are established through the HTTP/1.1 +upgrade mechanism, Websocket handlers need to be able to first +receive the HTTP request for the upgrade, before switching to +Websocket and taking over the connection. They can then receive +or send Websocket frames, handle incoming Erlang messages or +close the connection.</p></div> +<div class="sect1"> +<h2 id="_upgrade">Upgrade</h2> +<div class="sectionbody"> +<div class="paragraph"><p>The <code>init/2</code> callback is called when the request is received. +To establish a Websocket connection, you must switch to the +<code>cowboy_websocket</code> module:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>Cowboy will perform the Websocket handshake immediately. Note +that the handshake will fail if the client did not request an +upgrade to Websocket.</p></div> +<div class="paragraph"><p>The Req object becomes unavailable after this function returns. +Any information required for proper execution of the Websocket +handler must be saved in the state.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_subprotocol">Subprotocol</h2> +<div class="sectionbody"> +<div class="paragraph"><p>The client may provide a list of Websocket subprotocols it +supports in the sec-websocket-protocol header. The server <strong>must</strong> +select one of them and send it back to the client or the +handshake will fail.</p></div> +<div class="paragraph"><p>For example, a client could understand both STOMP and MQTT over +Websocket, and provide the header:</p></div> +<div class="listingblock"> +<div class="content"> +<pre><code>sec-websocket-protocol: v12.stomp, mqtt</code></pre> +</div></div> +<div class="paragraph"><p>If the server only understands MQTT it can return:</p></div> +<div class="listingblock"> +<div class="content"> +<pre><code>sec-websocket-protocol: mqtt</code></pre> +</div></div> +<div class="paragraph"><p>This selection must be done in <code>init/2</code>. An example usage could +be:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">cowboy_req:parse_header</span></span>(<span style="color: #990000"><<</span><span style="color: #FF0000">"sec-websocket-protocol"</span><span style="color: #990000">>></span>, <span style="color: #009900">Req</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span> + <span style="color: #000080">undefined</span> <span style="color: #990000">-></span> + {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}; + <span style="color: #009900">Subprotocols</span> <span style="color: #990000">-></span> + <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">lists:keymember</span></span>(<span style="color: #990000"><<</span><span style="color: #FF0000">"mqtt"</span><span style="color: #990000">>></span>, <span style="color: #993399">1</span>, <span style="color: #009900">Subprotocols</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span> + <span style="color: #000080">true</span> <span style="color: #990000">-></span> + <span style="color: #009900">Req2</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">cowboy_req:set_resp_header</span></span>(<span style="color: #990000"><<</span><span style="color: #FF0000">"sec-websocket-protocol"</span><span style="color: #990000">>></span>, + <span style="color: #990000"><<</span><span style="color: #FF0000">"mqtt"</span><span style="color: #990000">>></span>, <span style="color: #009900">Req</span>), + {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req2</span>, <span style="color: #009900">State</span>}; + <span style="color: #000080">false</span> <span style="color: #990000">-></span> + {<span style="color: #FF6600">stop</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>} + <span style="font-weight: bold"><span style="color: #0000FF">end</span></span> + <span style="font-weight: bold"><span style="color: #0000FF">end</span></span><span style="color: #990000">.</span></tt></pre></div></div> +</div> +</div> +<div class="sect1"> +<h2 id="_post_upgrade_initialization">Post-upgrade initialization</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Cowboy has separate processes for handling the connection +and requests. Because Websocket takes over the connection, +the Websocket protocol handling occurs in a different +process than the request handling.</p></div> +<div class="paragraph"><p>This is reflected in the different callbacks Websocket +handlers have. The <code>init/2</code> callback is called from the +temporary request process and the <code>websocket_</code> callbacks +from the connection process.</p></div> +<div class="paragraph"><p>This means that some initialization cannot be done from +<code>init/2</code>. Anything that would require the current pid, +or be tied to the current pid, will not work as intended. +The optional <code>websocket_init/1</code> can be used instead:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-></span> + <span style="font-weight: bold"><span style="color: #000000">erlang:start_timer</span></span>(<span style="color: #993399">1000</span>, <span style="font-weight: bold"><span style="color: #000080">self</span></span>(), <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>), + {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>All Websocket callbacks share the same return values. This +means that we can send frames to the client right after +the upgrade:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +</div> +</div> +<div class="sect1"> +<h2 id="_receiving_frames">Receiving frames</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Cowboy will call <code>websocket_handle/2</code> whenever a text, binary, +ping or pong frame arrives from the client.</p></div> +<div class="paragraph"><p>The handler can handle or ignore the frames. It can also +send frames back to the client or stop the connection.</p></div> +<div class="paragraph"><p>The following snippet echoes back any text frame received and +ignores all others:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">Frame</span> <span style="color: #990000">=</span> {<span style="color: #FF6600">text</span>, <span style="color: #990000">_</span>}, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">reply</span>, <span style="color: #009900">Frame</span>, <span style="color: #009900">State</span>}; +<span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">_Frame</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>Note that ping and pong frames require no action from the +handler as Cowboy will automatically reply to ping frames. +They are provided for informative purposes only.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_receiving_erlang_messages">Receiving Erlang messages</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Cowboy will call <code>websocket_info/2</code> whenever an Erlang message +arrives.</p></div> +<div class="paragraph"><p>The handler can handle or ignore the messages. It can also +send frames to the client or stop the connection.</p></div> +<div class="paragraph"><p>The following snippet forwards log messages to the client +and ignores all others:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>({<span style="font-weight: bold"><span style="color: #000080">log</span></span>, <span style="color: #009900">Text</span>}, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #009900">Text</span>}, <span style="color: #009900">State</span>}; +<span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +</div> +</div> +<div class="sect1"> +<h2 id="_sending_frames">Sending frames</h2> +<div class="sectionbody"> +<div class="paragraph"><p>All <code>websocket_</code> callbacks share return values. They may +send zero, one or many frames to the client.</p></div> +<div class="paragraph"><p>To send nothing, just return an ok tuple:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>To send one frame, return a reply tuple with the frame to send:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>You can send frames of any type: text, binary, ping, pong +or close frames.</p></div> +<div class="paragraph"><p>To send many frames at once, return a reply tuple with the +list of frames to send:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">reply</span>, [ + {<span style="color: #FF6600">text</span>, <span style="color: #FF0000">"Hello"</span>}, + {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"world!"</span><span style="color: #990000">>></span>}, + {<span style="font-weight: bold"><span style="color: #000080">binary</span></span>, <span style="color: #990000"><<</span><span style="color: #993399">0</span><span style="color: #990000">:</span><span style="color: #993399">8000</span><span style="color: #990000">>></span>} + ], <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>They are sent in the given order.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_keeping_the_connection_alive">Keeping the connection alive</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Cowboy will automatically respond to ping frames sent by +the client. They are still forwarded to the handler for +informative purposes, but no further action is required.</p></div> +<div class="paragraph"><p>Cowboy does not send ping frames itself. The handler can +do it if required. A better solution in most cases is to +let the client handle pings. Doing it from the handler +would imply having an additional timer per connection and +this can be a considerable cost for servers that need to +handle large numbers of connections.</p></div> +<div class="paragraph"><p>Cowboy can be configured to close idle connections +automatically. It is highly recommended to configure +a timeout here, to avoid having processes linger longer +than needed.</p></div> +<div class="paragraph"><p>The <code>init/2</code> callback can set the timeout to be used +for the connection. For example, this would make Cowboy +close connections idle for more than 30 seconds:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>, #{ + <span style="color: #0000FF">idle_timeout</span> <span style="color: #990000">=></span> <span style="color: #993399">30000</span>}}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>This value cannot be changed once it is set. It defaults to +<code>60000</code>.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_saving_memory">Saving memory</h2> +<div class="sectionbody"> +<div class="paragraph"><p>The Websocket connection process can be set to hibernate +after the callback returns.</p></div> +<div class="paragraph"><p>Simply add an <code>hibernate</code> field to the ok or reply tuples:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span> + +<span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">_Frame</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span> + +<span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>It is highly recommended to write your handlers with +hibernate enabled, as this allows to greatly reduce the +memory usage. Do note however that an increase in the +CPU usage or latency can be observed instead, in particular +for the more busy connections.</p></div> +</div> +</div> +<div class="sect1"> +<h2 id="_closing_the_connection">Closing the connection</h2> +<div class="sectionbody"> +<div class="paragraph"><p>The connection can be closed at any time, either by telling +Cowboy to stop it or by sending a close frame.</p></div> +<div class="paragraph"><p>To tell Cowboy to close the connection, use a stop tuple:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.8 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-></span> + {<span style="color: #FF6600">stop</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>Sending a <code>close</code> frame will immediately initiate the closing +of the Websocket connection. Note that when sending a list of +frames that include a close frame, any frame found after the +close frame will not be sent.</p></div> +</div> +</div> + + + <nav style="margin:1em 0"> |