### ----------------------------------------------------
### -- cro
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Worthington <jnthn@jnthn.net>
### -- File: docs/reference/cro-http-router-websocket.md
### ----------------------------------------------------
# Cro::HTTP::Router::WebSocket

This exports a subroutine `web-socket` that is to be used inside of a
`Cro::HTTP::Router` `get` handler. This makes it easy to use WebSockets inside
of a HTTP application built using the router.

## Basic usage

The `web-socket` subroutine takes a code block, which will - per new WebSocket
connection - receive a `Supply` argument. This `Supply` will emit a
`Cro::WebSocket::Message` for each message received from the client. The
block is expected to return a `Supply` that will `emit` messages to be sent to
the client.

Thus, a highly simplified chat server might be written as:

```
my $chat = Supplier.new;

get -> 'chat' {
    web-socket -> $incoming {
        supply {
            whenever $incoming -> $message {
                $chat.emit(await $message.body-text);
            }
            whenever $chat -> $text {
                emit $text;
            }
        }
    }
}
```

## Receiving close messages

If the block passed to `web-socket` has two parameters, the second one shall
be passed a `Promise` that will be kept with any Close message sent by the
client, or alternatively when the socket is closed from the server side.

```
my $chat = Supplier.new;

get -> 'chat' {
    web-socket -> $incoming, $close {
        supply {
            whenever $incoming -> $message {
                $chat.emit(await $message.body-text);
            }
            whenever $chat -> $text {
                emit $text;
            }
            whenever $close {
                $chat.emit("A user left the chat");
            }
        }
    }
}
```

## Body parsing and serialization

Body parsers (implementing the `Cro::BodyParser` role) and body serializers
(implementing the `Cro::BodySerializer` role) may be passed to `web-socket`.
These allow for easier processing of, for example, JSON messages.

```
use Cro::WebSocket::BodyParsers;
use Cro::WebSocket::BodySerializers;

# Receives JSON messages like:
#   { "input": "देवनागरी" }
# And produces messages like:
#   { "result": 5 }
get -> 'graphemes' {
    web-socket
        :body-parsers(Cro::WebSocket::BodyParser::JSON),
        :body-serializers(Cro::WebSocket::BodySerializer::JSON),
        -> $incoming {
            supply whenever $incoming -> $message {
                my $json = await $message.body;
                emit { result => $json<input>.chars };
            }
        }
}
```

Since working with JSON is so common, there is a shortcut `:json` argument
to `web-socket` that configures the body parser and serializer as seen in the
previous example, reducing it to just:

```
get -> 'graphemes' {
    web-socket :json, -> $incoming {
        supply whenever $incoming -> $message {
            my $json = await $message.body;
            emit { result => $json<input>.chars };
        }
    }
}
```


