State in Cowboy Websockets

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

State in Cowboy Websockets

Noah Silverman
Hello,

I've written a fairly standard websocket handler using Cowboy 2.4.  It correctly accepts websockts, and handles messages in both directions.  Cowboy's built in functionality makes this simple.

However, I can't find a way to store any state for a websocket connection.  Cowboy creates a separate PID for each connection, so theoretically we should be able to have each PID keep state (like any other erlang process or gen_server.) I'd like users to be able to do things like authenticate, set preferences, etc. for a websocket connection.  the easiest way to handle this would be to simply save a few variable sin state, as we do in any other gen_server process. 

The Cowboy Websocket handler *does* have a state variable that gets passed through calls, HOWEVER there is no way to define the state record like we'd do with other gen_server processes.  I tried simply adding the record definition to the top of the handler file (standard workflow for gen_server), but Cowboy then crashes with an undefined record error when I try to use the state record.

Does anybody have any ideas on haw to handle this, or a potential solutions?

Thank You!

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

publickey - noah@helios.ai - 0xBCEFA873.asc (4K) Download Attachment
signature.asc (875 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: State in Cowboy Websockets

Loïc Hoguin-3
Hello,

Without seeing your code I have no idea why you think you can't use a
record for the state.

Just do:

init(Req, _) ->
     {cowboy_websocket, Req, #state{}}.

On 10/01/2018 06:52 AM, Noah Silverman wrote:

> Hello,
>
> I've written a fairly standard websocket handler using Cowboy 2.4.  It
> correctly accepts websockts, and handles messages in both directions.  
> Cowboy's built in functionality makes this simple.
>
> However, I can't find a way to store any state for a websocket
> connection.  Cowboy creates a separate PID for each connection, so
> theoretically we should be able to have each PID keep state (like any
> other erlang process or gen_server.) I'd like users to be able to do
> things like authenticate, set preferences, etc. for a websocket
> connection.  the easiest way to handle this would be to simply save a
> few variable sin state, as we do in any other gen_server process.
>
> The Cowboy Websocket handler *does* have a state variable that gets
> passed through calls, HOWEVER there is no way to define the state record
> like we'd do with other gen_server processes.  I tried simply adding the
> record definition to the top of the handler file (standard workflow for
> gen_server), but Cowboy then crashes with an undefined record error when
> I try to use the state record.
>
> Does anybody have any ideas on haw to handle this, or a potential solutions?
>
> Thank You!
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>

--
Loïc Hoguin
https://ninenines.eu
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: State in Cowboy Websockets

Noah Silverman
Here's a relevant snippet of code.  I'm attempting to store the IP of the request in the State.  One guess is that the problem arises because I'm attempting to use the State variable passed into init.

===============

-record(state,{
    ip
}).

init(Req0, State) ->
    {IP,_Port} = maps:get(peer,Req0, {0,0}),

    Opts = #{idle_timeout => 600000,  max_frame_size => 256},

    {cowboy_websocket, Req0, State#state{ip=IP}, Opts}.


===============


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Monday, October 1, 2018 1:48 PM, Loïc Hoguin <[hidden email]> wrote:

> Hello,
>

> Without seeing your code I have no idea why you think you can't use a
> record for the state.
>

> Just do:
>

> init(Req, _) ->
>

>      {cowboy_websocket, Req, #state{}}.
>    

>

> On 10/01/2018 06:52 AM, Noah Silverman wrote:
>

> > Hello,
> > I've written a fairly standard websocket handler using Cowboy 2.4.  It
> > correctly accepts websockts, and handles messages in both directions.
> > Cowboy's built in functionality makes this simple.
> > However, I can't find a way to store any state for a websocket
> > connection.  Cowboy creates a separate PID for each connection, so
> > theoretically we should be able to have each PID keep state (like any
> > other erlang process or gen_server.) I'd like users to be able to do
> > things like authenticate, set preferences, etc. for a websocket
> > connection.  the easiest way to handle this would be to simply save a
> > few variable sin state, as we do in any other gen_server process.
> > The Cowboy Websocket handler does have a state variable that gets
> > passed through calls, HOWEVER there is no way to define the state record
> > like we'd do with other gen_server processes.  I tried simply adding the
> > record definition to the top of the handler file (standard workflow for
> > gen_server), but Cowboy then crashes with an undefined record error when
> > I try to use the state record.
> > Does anybody have any ideas on haw to handle this, or a potential solutions?
> > Thank You!
> >

> > erlang-questions mailing list
> > [hidden email]
> > http://erlang.org/mailman/listinfo/erlang-questions
>

> --
>

> Loïc Hoguin
> https://ninenines.eu


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

publickey - noah@helios.ai - 0xBCEFA873.asc (4K) Download Attachment
signature.asc (875 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: State in Cowboy Websockets

Loïc Hoguin-3
Your guess is correct. The initial state is whatever you configured in
routing, so if it's not a #state{} it's not going to work.

On 10/01/2018 08:25 AM, Noah Silverman wrote:

> Here's a relevant snippet of code.  I'm attempting to store the IP of the request in the State.  One guess is that the problem arises because I'm attempting to use the State variable passed into init.
>
> ===============
>
> -record(state,{
>      ip
> }).
>
> init(Req0, State) ->
>      {IP,_Port} = maps:get(peer,Req0, {0,0}),
>
>      Opts = #{idle_timeout => 600000,  max_frame_size => 256},
>
>      {cowboy_websocket, Req0, State#state{ip=IP}, Opts}.
>
>
> ===============
>
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Monday, October 1, 2018 1:48 PM, Loïc Hoguin <[hidden email]> wrote:
>
>> Hello,
>>
>
>> Without seeing your code I have no idea why you think you can't use a
>> record for the state.
>>
>
>> Just do:
>>
>
>> init(Req, _) ->
>>
>
>>       {cowboy_websocket, Req, #state{}}.
>>      
>
>>
>
>> On 10/01/2018 06:52 AM, Noah Silverman wrote:
>>
>
>>> Hello,
>>> I've written a fairly standard websocket handler using Cowboy 2.4.  It
>>> correctly accepts websockts, and handles messages in both directions.
>>> Cowboy's built in functionality makes this simple.
>>> However, I can't find a way to store any state for a websocket
>>> connection.  Cowboy creates a separate PID for each connection, so
>>> theoretically we should be able to have each PID keep state (like any
>>> other erlang process or gen_server.) I'd like users to be able to do
>>> things like authenticate, set preferences, etc. for a websocket
>>> connection.  the easiest way to handle this would be to simply save a
>>> few variable sin state, as we do in any other gen_server process.
>>> The Cowboy Websocket handler does have a state variable that gets
>>> passed through calls, HOWEVER there is no way to define the state record
>>> like we'd do with other gen_server processes.  I tried simply adding the
>>> record definition to the top of the handler file (standard workflow for
>>> gen_server), but Cowboy then crashes with an undefined record error when
>>> I try to use the state record.
>>> Does anybody have any ideas on haw to handle this, or a potential solutions?
>>> Thank You!
>>>
>
>>> erlang-questions mailing list
>>> [hidden email]
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>> --
>>
>
>> Loïc Hoguin
>> https://ninenines.eu
>

--
Loïc Hoguin
https://ninenines.eu
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: State in Cowboy Websockets

Noah Silverman
Ahhh, that makes perfect sense.

It works!

Thank you!!!



‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Monday, October 1, 2018 2:34 PM, Loïc Hoguin <[hidden email]> wrote:

> Your guess is correct. The initial state is whatever you configured in
> routing, so if it's not a #state{} it's not going to work.
>

> On 10/01/2018 08:25 AM, Noah Silverman wrote:
>

> > Here's a relevant snippet of code. I'm attempting to store the IP of the request in the State. One guess is that the problem arises because I'm attempting to use the State variable passed into init.
> > ===============
> > -record(state,{
> > ip
> > }).
> > init(Req0, State) ->
> > {IP,_Port} = maps:get(peer,Req0, {0,0}),
> >

> >      Opts = #{idle_timeout => 600000,  max_frame_size => 256},
> >    

> >      {cowboy_websocket, Req0, State#state{ip=IP}, Opts}.
> >    

> >

> > ===============
> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> > On Monday, October 1, 2018 1:48 PM, Loïc Hoguin [hidden email] wrote:
> >

> > > Hello,
> >

> > > Without seeing your code I have no idea why you think you can't use a
> > > record for the state.
> >

> > > Just do:
> >

> > > init(Req, _) ->
> >

> > >       {cowboy_websocket, Req, #state{}}.
> > >    

> >

> > >

> >

> > > On 10/01/2018 06:52 AM, Noah Silverman wrote:
> >

> > > > Hello,
> > > > I've written a fairly standard websocket handler using Cowboy 2.4.  It
> > > > correctly accepts websockts, and handles messages in both directions.
> > > > Cowboy's built in functionality makes this simple.
> > > > However, I can't find a way to store any state for a websocket
> > > > connection.  Cowboy creates a separate PID for each connection, so
> > > > theoretically we should be able to have each PID keep state (like any
> > > > other erlang process or gen_server.) I'd like users to be able to do
> > > > things like authenticate, set preferences, etc. for a websocket
> > > > connection.  the easiest way to handle this would be to simply save a
> > > > few variable sin state, as we do in any other gen_server process.
> > > > The Cowboy Websocket handler does have a state variable that gets
> > > > passed through calls, HOWEVER there is no way to define the state record
> > > > like we'd do with other gen_server processes.  I tried simply adding the
> > > > record definition to the top of the handler file (standard workflow for
> > > > gen_server), but Cowboy then crashes with an undefined record error when
> > > > I try to use the state record.
> > > > Does anybody have any ideas on haw to handle this, or a potential solutions?
> > > > Thank You!
> >

> > > > erlang-questions mailing list
> > > > [hidden email]
> > > > http://erlang.org/mailman/listinfo/erlang-questions
> >

> > > --
> >

> > > Loïc Hoguin
> > > https://ninenines.eu
>

> --
>

> Loïc Hoguin
> https://ninenines.eu


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

publickey - noah@helios.ai - 0xBCEFA873.asc (4K) Download Attachment
signature.asc (875 bytes) Download Attachment