diff options
author | Loïc Hoguin <[email protected]> | 2018-04-04 13:13:37 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2018-04-04 13:13:37 +0200 |
commit | d2a3f2cedd7c00d0933222aed9c06b3149aa4db4 (patch) | |
tree | 4f1499bac639c782b250af0fbf0dec2064315813 /docs/en/cowboy/2.3/guide/ws_handlers | |
parent | 1d654719f5fa6be67d2c95145872068665702cb7 (diff) | |
download | ninenines.eu-d2a3f2cedd7c00d0933222aed9c06b3149aa4db4.tar.gz ninenines.eu-d2a3f2cedd7c00d0933222aed9c06b3149aa4db4.tar.bz2 ninenines.eu-d2a3f2cedd7c00d0933222aed9c06b3149aa4db4.zip |
Cowboy 2.3.0
Diffstat (limited to 'docs/en/cowboy/2.3/guide/ws_handlers')
-rw-r--r-- | docs/en/cowboy/2.3/guide/ws_handlers/index.html | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/docs/en/cowboy/2.3/guide/ws_handlers/index.html b/docs/en/cowboy/2.3/guide/ws_handlers/index.html new file mode 100644 index 00000000..15fcd919 --- /dev/null +++ b/docs/en/cowboy/2.3/guide/ws_handlers/index.html @@ -0,0 +1,458 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <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.37.1" /> + + <title>Nine Nines: Websocket handlers</title> + + <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic' rel='stylesheet' type='text/css'> + <link href="/css/99s.css?r=1" rel="stylesheet"> + + <link rel="shortcut icon" href="/img/ico/favicon.ico"> + <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/ico/apple-touch-icon-114.png"> + <link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/ico/apple-touch-icon-72.png"> + <link rel="apple-touch-icon-precomposed" href="/img/ico/apple-touch-icon-57.png"> + + +</head> + + +<body class=""> + <header id="page-head"> + <div id="topbar" class="container"> + <div class="row"> + <div class="span2"> + <h1 id="logo"><a href="/" title="99s">99s</a></h1> + </div> + <div class="span10"> + + <div id="side-header"> + <nav> + <ul> + <li><a title="Hear my thoughts" href="/articles">Articles</a></li> + <li><a title="Watch my talks" href="/talks">Talks</a></li> + <li class="active"><a title="Read the docs" href="/docs">Documentation</a></li> + <li><a title="Request my services" href="/services">Consulting & Training</a></li> + </ul> + </nav> + <ul id="social"> + <li> + <a href="https://github.com/ninenines" title="Check my Github repositories"><img src="/img/ico_github.png" data-hover="/img/ico_github_alt.png" alt="Github"></a> + </li> + <li> + <a title="Keep in touch!" href="http://twitter.com/lhoguin"><img src="/img/ico_microblog.png" data-hover="/img/ico_microblog_alt.png"></a> + </li> + <li> + <a title="Contact me" href="mailto:[email protected]"><img src="/img/ico_mail.png" data-hover="/img/ico_mail_alt.png"></a> + </li> + </ul> + </div> + </div> + </div> + </div> + + +</header> + +<div id="contents" class="two_col"> +<div class="container"> +<div class="row"> +<div id="docs" class="span9 maincol"> + +<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 +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 +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">Req0</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">Req0</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">Req0</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">Req</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">Req0</span>), + {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}; + <span style="color: #000080">false</span> <span style="color: #990000">-></span> + <span style="color: #009900">Req</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">cowboy_req:reply</span></span>(<span style="color: #993399">400</span>, <span style="color: #009900">Req0</span>), + {<span style="color: #FF6600">ok</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 +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 +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 +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 +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 +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 +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 +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 +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="_limiting_frame_sizes">Limiting frame sizes</h2> +<div class="sectionbody"> +<div class="paragraph"><p>Cowboy accepts frames of any size by default. You should +limit the size depending on what your handler may handle. +You can do this via the <code>init/2</code> callback:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight +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">max_frame_size</span> <span style="color: #990000">=></span> <span style="color: #993399">8000000</span>}}<span style="color: #990000">.</span></tt></pre></div></div> +<div class="paragraph"><p>The lack of limit is historical. A future version of +Cowboy will have a more reasonable default.</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 +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 +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 class="paragraph"><p>The following example sends a close frame with a reason message:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight +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">close</span>, <span style="color: #993399">1000</span>, <span style="color: #990000"><<</span><span style="color: #FF0000">"some-reason"</span><span style="color: #990000">>></span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div> +</div> +</div> + + + + + + + + + + + <nav style="margin:1em 0"> + + <a style="float:left" href="https://ninenines.eu/docs/en/cowboy/2.3/guide/ws_protocol/"> + The Websocket protocol + </a> + + + + <a style="float:right" href="https://ninenines.eu/docs/en/cowboy/2.3/guide/streams/"> + Streams + </a> + + </nav> + + + + +</div> + +<div class="span3 sidecol"> + + +<h3> + Cowboy + 2.3 + + User Guide +</h3> + +<ul> + + <li><a href="/docs/en/cowboy/2.3/guide">User Guide</a></li> + + + <li><a href="/docs/en/cowboy/2.3/manual">Function Reference</a></li> + + +</ul> + +<h4 id="docs-nav">Navigation</h4> + +<h4>Version select</h4> +<ul> + + + + <li><a href="/docs/en/cowboy/2.3/guide">2.3</a></li> + + <li><a href="/docs/en/cowboy/2.2/guide">2.2</a></li> + + <li><a href="/docs/en/cowboy/2.1/guide">2.1</a></li> + + <li><a href="/docs/en/cowboy/2.0/guide">2.0</a></li> + + <li><a href="/docs/en/cowboy/1.0/guide">1.0</a></li> + +</ul> + +</div> +</div> +</div> +</div> + + <footer> + <div class="container"> + <div class="row"> + <div class="span6"> + <p id="scroll-top"><a href="#">↑ Scroll to top</a></p> + <nav> + <ul> + <li><a href="mailto:[email protected]" title="Contact us">Contact us</a></li><li><a href="https://github.com/ninenines/ninenines.github.io" title="Github repository">Contribute to this site</a></li> + </ul> + </nav> + </div> + <div class="span6 credits"> + <p><img src="/img/footer_logo.png"></p> + <p>Copyright © Loïc Hoguin 2012-2016</p> + </div> + </div> + </div> + </footer> + + + <script src="/js/custom.js"></script> + </body> +</html> + + |