I'd like to create a websocket app in Cowboy that gets its data from another Cowboy handler. Let's say that I want to combine the Echo_get example from cowboy: https://github.com/ninenines/cowboy/tree/master/examples/echo_get/src
with websocket example
https://github.com/ninenines/cowboy/tree/master/examples/websocket/src
in such a way that a GET request to Echo should send a "push" via websocket handler to the html page in that example.
What is the least complicated way to do it? Can I use "pipe" operator in some easy way ? Do I need to create and intermediate gen_something to pass messages between them? I would appreciate an answer with sample code that shows the glue code for the handlers - I do not really know where to start plumbing the two handlers together.
A websocket handler in cowboy is a long lived request process to which you can send websocket or erlang messages.
In your case, there are 2 types of processes:
- websocket processes: websocket handlers with a websocket connection opened to clients.
- echo processes: processes when a client access the echo handler with a parameter.
The idea is that the echo process sends an erlang message to the websocket processes, that in turn will send a message to the client.
For your echo process can send a message to your websocket processes, you need to keep a list of websocket processes to which you want to send messages. Gproc is a quite useful library for that purpose.
You can register processes to gproc pubsub with gproc_ps:subscribe/2
, and send messages to the registered processes with gproc_ps:publish/3
.
Cowboy websocket processes receive erlang messages with the websocket_info/3 function.
So for example, the websocket handler could be like this:
websocket_init(_, Req, _Opts) ->
...
% l is for local process registration
% echo is the name of the event you register the process to
gproc_ps:subscribe(l, echo),
...
websocket_info({gproc_ps_event, echo, Echo}, Req, State) ->
% sending the Echo to the client
{reply, {text, Echo}, Req, State};
And the echo handler like this:
echo(<<"GET">>, Echo, Req) ->
% sending the echo message to the websockets handlers
gproc_ps:publish(l, echo, Echo),
cowboy_req:reply(200, [
{<<"content-type">>, <<"text/plain; charset=utf-8">>}
], Echo, Req);