How do you use Gun as a Cowboy client?

半腔热情 提交于 2019-12-01 20:43:49

A summary of the issues/suggestions from the comments discussion

  1. For running your Erlang app (in this case including gun as a dependency), you need to have the path to beam and .app files discoverable to the shell. When using erlang.mk, the easiest way to do that would be running the release using make run

  2. On Cowboy side, to have Websocket handled correctly, you need to have a handler defined in your cowboy routes. See example in Cowboy Websocket example

See also Gun user guide for more details about handling Websocket in Gun

Success!

~/erlang_programs/my_gun/src/my.erl:

-module(my).
-compile(export_all).

get() ->
    ...

ws() ->

    {ok, _} = application:ensure_all_started(gun),
    {ok, ConnPid} = gun:open("localhost", 8080),
    {ok, _Protocol} = gun:await_up(ConnPid),

    gun:ws_upgrade(ConnPid, "/websocket"),

    receive
        {gun_ws_upgrade, ConnPid, ok, Headers} ->
                upgrade_success(ConnPid, Headers);
        {gun_response, ConnPid, _, _, Status, Headers} ->
                exit({ws_upgrade_failed, Status, Headers});
        {gun_error, _ConnPid, _StreamRef, Reason} ->
                exit({ws_upgrade_failed, Reason})
        %% More clauses here as needed.
    after 1000 ->
            exit(timeout)
    end,


upgrade_success(ConnPid, Headers) ->
    io:format("Upgraded ~w. Success!~nHeaders:~n~p~n", 
              [ConnPid, Headers]),

    gun:ws_send(ConnPid, {text, "It's raining!"}),

    receive
        {gun_ws, ConnPid, {text, Msg} } ->
            io:format("~s~n", [Msg])
    end.

On the cowboy side:

-module(myws_handler).
-compile(export_all).

init(Req, State) ->
    {cowboy_websocket, Req, State}.  %Perform websocket setup

websocket_handle({text, Msg}, State) ->
    {
     reply, 
     {text, io_lib:format("Server received: ~s", [Msg]) },
     State
    };
websocket_handle(_Other, State) ->  %Ignore
    {ok, State}. 

Here's the output:

~/erlang_programs/my_gun$ gmake run
gmake[1]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/cowlib'
gmake[2]: Entering directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
gmake[2]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/ranch'
 GEN    rebar.config
gmake[1]: Leaving directory '/Users/7stud/erlang_programs/my_gun/deps/gun'
 DEPEND my_gun.d
 ERLC   my.erl
 APP    my_gun
===> Starting relx build process ...
===> Resolving OTP Applications from directories:
          /Users/7stud/erlang_programs/my_gun/ebin
          /Users/7stud/erlang_programs/my_gun/deps
          /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang/lib
          /Users/7stud/erlang_programs/my_gun/apps
          /Users/7stud/erlang_programs/my_gun/_rel
===> Resolved my_gun_release-1
===> rendering builtin_hook_status hook to "/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/bin/hooks/builtin/status"
===> Including Erts from /Users/7stud/.evm/erlang_versions/otp_src_19.2/lib/erlang
===> release successfully created!
===> tarball /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/my_gun_release-1.tar.gz successfully created!
Exec: /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/erts-8.2/bin/erlexec -boot /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/my_gun_release -mode embedded -boot_var ERTS_LIB_DIR /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/lib -config /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/sys.config -args_file /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release/releases/1/vm.args -pa -- console
Root: /Users/7stud/erlang_programs/my_gun/_rel/my_gun_release
/Users/7stud/erlang_programs/my_gun/_rel/my_gun_release
heart_beat_kill_pid = 38883
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]


=PROGRESS REPORT==== 10-Jul-2017::18:04:38 ===
          supervisor: {local,sasl_safe_sup}
             started: [{pid,<0.353.0>},
                       {id,alarm_handler},
                       {mfargs,{alarm_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::18:04:38 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.352.0>},
                       {id,sasl_safe_sup},
                       {mfargs,
                           {supervisor,start_link,
                               [{local,sasl_safe_sup},sasl,safe]}},
                       {restart_type,permanent},
                       {shutdown,infinity},
                       {child_type,supervisor}]

=PROGRESS REPORT==== 10-Jul-2017::18:04:38 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.354.0>},
                       {id,release_handler},
                       {mfargs,{release_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::18:04:38 ===
         application: sasl
          started_at: 'my_gun@127.0.0.1'

=PROGRESS REPORT==== 10-Jul-2017::18:04:38 ===
          supervisor: {local,runtime_tools_sup}
             started: [{pid,<0.360.0>},
                       {id,ttb_autostart},
                       {mfargs,{ttb_autostart,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,3000},
                       {child_type,worker}]

=PROGRESS REPORT==== 10-Jul-2017::18:04:38 ===
         application: runtime_tools
          started_at: 'my_gun@127.0.0.1'
Eshell V8.2  (abort with ^G)

(my_gun@127.0.0.1)1> my:ws().

=PROGRESS REPORT==== 10-Jul-2017::18:04:41 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.367.0>},{mfa,{inet_gethost_native,init,[[]]}}]

=PROGRESS REPORT==== 10-Jul-2017::18:04:41 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.366.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]
Upgraded <0.365.0>. Success!
Headers:
[{<<"connection">>,<<"Upgrade">>},
 {<<"date">>,<<"Tue, 11 Jul 2017 00:04:40 GMT">>},
 {<<"sec-websocket-accept">>,<<"pYv8QeeJfzQgaS/x8flZHyrIexk=">>},
 {<<"server">>,<<"Cowboy">>},
 {<<"upgrade">>,<<"websocket">>}]
Server received: It's raining!
ok

(my_gun@127.0.0.1)2> 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!