2016-01-14 13:35:25 +01:00
|
|
|
[[ws_protocol]]
|
|
|
|
== The Websocket protocol
|
2014-03-03 16:59:02 +01:00
|
|
|
|
|
|
|
This chapter explains what Websocket is and why it is
|
|
|
|
a vital component of soft realtime Web applications.
|
|
|
|
|
2016-01-14 13:35:25 +01:00
|
|
|
=== Description
|
2014-03-03 16:59:02 +01:00
|
|
|
|
|
|
|
Websocket is an extension to HTTP that emulates plain TCP
|
|
|
|
connections between the client, typically a Web browser,
|
|
|
|
and the server. It uses the HTTP Upgrade mechanism to
|
|
|
|
establish the connection.
|
|
|
|
|
2016-09-01 17:42:41 +02:00
|
|
|
Websocket connections are fully asynchronous, unlike
|
|
|
|
HTTP/1.1 (synchronous) and HTTP/2 (asynchronous, but the
|
|
|
|
server can only initiate streams in response to requests).
|
|
|
|
With Websocket, the client and the server can both send
|
|
|
|
frames at any time without any restriction. It is closer
|
|
|
|
to TCP than any of the HTTP protocols.
|
2014-03-03 16:59:02 +01:00
|
|
|
|
|
|
|
Websocket is an IETF standard. Cowboy supports the standard
|
|
|
|
and all drafts that were previously implemented by browsers,
|
|
|
|
excluding the initial flawed draft sometimes known as
|
|
|
|
"version 0".
|
|
|
|
|
2016-09-01 17:42:41 +02:00
|
|
|
=== Websocket vs HTTP/2
|
|
|
|
|
|
|
|
For a few years Websocket was the only way to have a
|
|
|
|
bidirectional asynchronous connection with the server.
|
|
|
|
This changed when HTTP/2 was introduced. While HTTP/2
|
|
|
|
requires the client to first perform a request before
|
|
|
|
the server can push data, this is only a minor restriction
|
|
|
|
as the client can do so just as it connects.
|
|
|
|
|
|
|
|
Websocket was designed as a kind-of-TCP channel to a
|
|
|
|
server. It only defines the framing and connection
|
|
|
|
management and lets the developer implement a protocol
|
|
|
|
on top of it. For example you could implement IRC over
|
|
|
|
Websocket and use a Javascript IRC client to speak to
|
|
|
|
the server.
|
|
|
|
|
|
|
|
HTTP/2 on the other hand is just an improvement over
|
|
|
|
the HTTP/1.1 connection and request/response mechanism.
|
|
|
|
It has the same semantics as HTTP/1.1.
|
|
|
|
|
|
|
|
If all you need is to access an HTTP API, then HTTP/2
|
|
|
|
should be your first choice. On the other hand, if what
|
|
|
|
you need is a different protocol, then you can use
|
|
|
|
Websocket to implement it.
|
|
|
|
|
2016-01-14 13:35:25 +01:00
|
|
|
=== Implementation
|
2014-03-03 16:59:02 +01:00
|
|
|
|
|
|
|
Cowboy implements Websocket as a protocol upgrade. Once the
|
2014-09-30 20:12:13 +03:00
|
|
|
upgrade is performed from the `init/2` callback, Cowboy
|
2014-03-03 16:59:02 +01:00
|
|
|
switches to Websocket. Please consult the next chapter for
|
|
|
|
more information on initiating and handling Websocket
|
|
|
|
connections.
|
|
|
|
|
|
|
|
The implementation of Websocket in Cowboy is validated using
|
|
|
|
the Autobahn test suite, which is an extensive suite of tests
|
|
|
|
covering all aspects of the protocol. Cowboy passes the
|
|
|
|
suite with 100% success, including all optional tests.
|
|
|
|
|
|
|
|
Cowboy's Websocket implementation also includes the
|
2016-09-01 17:42:41 +02:00
|
|
|
permessage-deflate and x-webkit-deflate-frame compression
|
|
|
|
extensions.
|
|
|
|
|
Allow passing options to sub protocols
Before this commit we had an issue where configuring a
Websocket connection was simply not possible without
doing magic, adding callbacks or extra return values.
The init/2 function only allowed setting hibernate
and timeout options.
After this commit, when switching to a different
type of handler you can either return
{module, Req, State}
or
{module, Req, State, Opts}
where Opts is any value (as far as the sub protocol
interface is concerned) and is ultimately checked
by the custom handlers.
A large protocol like Websocket would accept only
a map there, with many different options, while a
small interface like loop handlers would allow
passing hibernate and nothing else.
For Websocket, hibernate must be set from the
websocket_init/1 callback, because init/2 executes
in a separate process.
Sub protocols now have two callbacks: one with the
Opts value, one without.
The loop handler code was largely reworked and
simplified. It does not need to manage a timeout
or read from the socket anymore, it's the job of
the protocol code. A lot of unnecessary stuff was
therefore removed.
Websocket compression must now be enabled from
the handler options instead of per listener. This
means that a project can have two separate Websocket
handlers with different options. Compression is
still disabled by default, and the idle_timeout
value was changed from inifnity to 60000 (60 seconds),
as that's safer and is also a good value for mobile
devices.
2017-02-18 18:26:20 +01:00
|
|
|
Cowboy will automatically use compression when the
|
|
|
|
`compress` option is returned from the `init/2` function.
|