如何将Cowboy(Erlang)websocket连接到webflow.io生成的网页



我想使用牛仔websocket接口与webflow生成的网页进行交互。我想举一个简单的例子,说明如何添加javascript实现连接到webflow HTML的websocket。

这应该会让你开始:

  1. Container(即div(拖到页面上。给它IDserver_info

  2. Button拖到页面上。给它IDget_server_info

  3. Page Settings允许您向页面添加javascript。用websocket连接到服务器的js看起来像这样:

    <script>
    var ws = new WebSocket("ws://localhost:8080/please_upgrade_to_websocket");
    ws.onerror = function(event) {
    console.error("[ME]WebSocket error observed:", event);
    };
    ws.onclose = function(event) {
    console.log("[ME]WebSocket is closed now.");
    };
    $("#get_server_info").click(function() {
    if(ws.readyState == 1) {               
    ws.send("My data");
    }
    else {
    alert("Websocket not open! readyState: " + ws.readyState);
    }
    });
    ws.onmessage = function (event) {
    alert("Data was retrieved from server and will be inserted in page.");
    $("#server_info").text(event.data);
    };
    </script>
    
  4. 创建一个名为hello_erlang的新牛仔应用程序。

  5. 创建一些路由,并通过在hello_erlang/src/hello_erlang_app.erl:中放入以下内容来指定它们的处理程序函数

    -module(hello_erlang_app).
    -behaviour(application).
    -export([start/2]).
    -export([stop/1]).
    start(_Type, _Args) ->
    HelloRoute = { "/", hello_handler, [] },
    WebSocketRoute = {"/please_upgrade_to_websocket", myws_handler, []},
    CatchallRoute = {"/[...]", no_matching_route_handler, []},
    Dispatch = cowboy_router:compile([
    {'_', [HelloRoute, WebSocketRoute, CatchallRoute]}
    ]),
    
    {ok, _} = cowboy:start_clear(my_http_listener,
    [{port, 8080}],
    #{env => #{dispatch => Dispatch} }
    ),
    hello_erlang_sup:start_link().
    stop(_State) ->
    ok.
    
  6. 为了提供带有按钮的简单html页面,我使用了hello_erlang/src/hello_handler.erl:

    -module(hello_handler).
    -behavior(cowboy_handler).
    -export([init/2]).
    init(Req0, State) ->
    io:format("[ME]Entered hello_handler~n"),
    Body = my_get_file("html/form.htm"),  %% Body can be a binary() or an iolist() (which is a list containing integers, strings, or binaries)
    Req = cowboy_req:reply(200,
    #{<<"content-type">> => <<"text/html">>},
    Body,
    Req0),
    {ok, Req, State}.
    my_get_file(Path) ->
    PrivDir = code:priv_dir(hello_erlang),  %% Finds the path of an application's priv directory
    AbsPath = filename:join([PrivDir, Path]),
    case file:read_file(AbsPath) of 
    {ok, Bin} -> Bin;
    _  -> ["<div>Cannot read file: ", Path, "</div>"]  %% iolist()
    end.
    

根据erlang文档,priv目录是应用程序特定文件的存放位置。下面是form.htm页面,我将其放在目录hello_erlang/priv/html/中(我创建了html目录(。在html页面的<head>部分,有一个<script>标签,它链接到jquery库,该库由javascript:使用

<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"   
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" 
crossorigin="anonymous">
</script>
</head>
<body>
<div id="server_info">Server info</div>
<button type="button" id="get_server_info">Get sever info</button>
<script>
var my_websocket = new WebSocket("ws://localhost:8080/please_upgrade_to_websocket");
my_websocket.onerror = function(event) {
console.error("[ME]WebSocket error observed:", event);
};
my_websocket.onclose = function(event) {
console.log("[ME]WebSocket is closed now.");
};
$("#get_server_info").click(function() {
if(my_websocket.readyState == 1) {               
my_websocket.send("My data");
}
else {
alert("Websocket not open! readyState: " + my_websocket.readyState );
}
});
my_websocket.onmessage = function (event) {
$("#server_info").text(event.data);
alert("Data was retrieved from server and will be inserted in page.");
};
</script>

</body>
</html>

编辑:提供html文件的另一种方法是取消hello_handler.erl并设置如下路由:

HelloRoute = { "/", cowboy_static, {priv_file, hello_erlang, "html/form.htm"} },

您可以将form.htm放在目录hello_erlang/priv/html/中(我创建了html目录(。请参阅有关静态文件的牛仔文档。当您在将html文件发送到客户端之前不需要使用erlang以某种方式更改html文件时,这是提供文件的最简单方法。

  1. hello_erlang/src/myws_handler.erl:

    -module(myws_handler).
    -export([init/2, websocket_init/1, websocket_handle/2, websocket_info/2]).
    
    init(Req, State) ->
    {cowboy_websocket, Req, State}.  %Perform websocket setup
    websocket_init(State) ->
    io:format("[ME]: Inside websocket_init()~n"),
    {ok, State}.
    websocket_handle({text, Msg}, State) ->
    {Hours, Minutes, Secs} = time(),
    {
    reply, 
    {text, io_lib:format("[~w:~w:~w]: Server received: ~s", [Hours, Minutes, Secs, Msg]) },
    State
    };
    websocket_handle(_Other, State) ->  %Ignore
    {ok, State}.
    
    websocket_info({text, Text}, State) ->
    {reply, {text, Text}, State};
    websocket_info(_Other, State) ->
    {ok, State}.
    
  2. hello_erlang/src/no_matching_route_handler.erl:

    -module(no_matching_route_handler).
    -behavior(cowboy_handler).
    -export([init/2]).
    init(Req0, State) -> %State comes from last argument of route
    Req = cowboy_req:reply(404,
    #{<<"content-type">> => <<"text/plain">>},
    <<"[ME] 404. Whoops! (No matching route!)">>,
    Req0),
    {ok, Req, State}.
    

然后,在应用程序的顶级目录中,在本例中为hello_erlang,启动牛仔服务器:

...cowboy_apps/hello_erlang$ make run

然后,在浏览器中输入以下网址:

http://localhost:8080/

这将导致牛仔提供包含该按钮的html页面。点击按钮会使用websocket向服务器发送一些数据,服务器会做出响应,然后js会在网页中插入响应。

Webflow实际上与答案无关:无论你如何或用什么来创建html和javascript,最终产品都是一个html页面,你可以把它放在服务器的目录中。当浏览器从服务器请求html文件时,服务器会将html文件发送到浏览器,然后浏览器读取文件并生成您看到的漂亮文本和图片,浏览器会在适当的时候执行javascript。浏览器不知道是谁创建了文件中的html和javascript。

最新更新