[[sub_protocols]]
== Sub protocols

Sub protocols are used for creating new types of handlers that
provide extra functionality in a reusable way. Cowboy uses this
mechanism to provide its loop, REST and Websocket handlers.

This chapter will explain how to create your own sub protocols
and handler types.

=== Usage

To switch to a sub protocol, the `init/2` callback must return
the name of the sub protocol module. Everything past this point
is handled by the sub protocol.

[source,erlang]
----
init(Req, State) ->
	{cowboy_websocket, Req, State}.
----

The return value may also have a `Timeout` value and/or the
atom `hibernate`. These options are useful for long living
connections. When they are not provided, the timeout value
defaults to `infinity` and the hibernate value to `run`.

The following snippet switches to the `my_protocol` sub
protocol, sets the timeout value to 5 seconds and enables
hibernation:

// @todo Yeah maybe what we really need is an Opts map.

[source,erlang]
----
init(Req, State) ->
	{my_protocol, Req, State, 5000, hibernate}.
----

If a sub protocol does not make use of these options, it should
crash if it receives anything other than the default values.

=== Upgrade

After the `init/2` function returns, Cowboy will then call the
`upgrade/6` function. This is the only callback defined by the
`cowboy_sub_protocol` behavior.

The function is named `upgrade` because it mimics the mechanism
of HTTP protocol upgrades. For some sub protocols, like Websocket,
an actual upgrade is performed. For others, like REST, this is
only an upgrade at Cowboy's level and the client has nothing to
do about it.

The upgrade callback receives the Req object, the middleware
environment, the handler and its options, and the aforementioned
timeout and hibernate values.

[source,erlang]
----
upgrade(Req, Env, Handler, HandlerOpts, Timeout, Hibernate) ->
	%% Sub protocol code here.
----

This callback is expected to behave like a middleware and to
return an updated environment and Req object.

Sub protocols are expected to call the `cowboy_handler:terminate/4`
function when they terminate. This function will make sure that
the optional `terminate/3` callback is called, if present.
