用cowboy构建嵌入式Web服务器

来源:互联网 发布:新三板源码 编辑:程序博客网 时间:2024/06/18 09:30

最近想用cowboy做一个echo服务器,经过几天的辛苦探索终于实现了,下面记录一下过程,源码等下会上传到Github。

系统:Ubuntu16.04

Erlang版本:20

cowboy版本:2.0.0

1、使用erlang.mk构建OTP release

简单列出一下命令,详细过程可以参考下面的链接。

$ mkdir hello_joe $ cd hello_joe$ wget https://erlang.mk/erlang.mkmake -f erlang.mk bootstrap bootstrap-relmake

如果编译提示在目录./.erlang.mk/下找不到relx文件,可以再make一下,第一次make会下载relx。

到这里已经构建好了一个基础的OTP release,其他工作可以在此基础上进行。

参考:https://erlang.mk/guide/getting_started.html

           https://ninenines.eu/docs/en/cowboy/2.0/guide/getting_started/  

2、给构建好的OTP release配置cowboy依赖

修改Makefile成下面这样:

PROJECT = echo_serverPROJECT_DESCRIPTION = New projectPROJECT_VERSION = 0.1.0DEPS = cowboydep_cowboy_commit = masterDEP_PLUGINS = cowboyinclude erlang.mk

键入make run,会自动下载cowboy及相关依赖到deps目录。

3、监听连接

修改src/echo_server_app.erl:

start(_Type, _Args) ->        Dispatch = cowboy_router:compile([                %% {URIHost, list({URIPath, Handler, Opts})}                {'_', [                        {"/test2.html", cowboy_static, {priv_file, echo_server, "test2.html"}},                        {"/cgi", cgi_web_server, []}                ]}        ]),        {ok, _} = cowboy:start_clear(my_http_listener,                [{port, 8080}],                #{env => #{dispatch => Dispatch}}        ),        echo_server_sup:start_link().

这里最重要的是配置路由表,路由表决定URI路径会映射到哪个处理模块。

cowboy_static是提供一个静态内容,这里将”/test2.html”映射到echo_server的priv目录下的test2.html。

cgi_web_server是我自己定义请求处理模块。

参考http://blog.imaou.com/erlang/2015/02/24/build_web_service_with_cowboy_and_relx_1.html

4、处理请求

用模板生成处理模块:

$ make new t=cowboy.http n=cgi_web_server
然后修改刚生成的处理模块:

cgi_web_server.erl:

-module(cgi_web_server).-behavior(cowboy_handler).-export([init/2]).init(Req, State) ->    Path = cowboy_req:path(Req),    handle1(Path, Req, State).handle1(<<"/cgi">>, Req, State) ->    ModFunBin = cowboy_req:parse_qs(Req),    {ok, Bin, Req2} = cowboy_req:read_body(Req),    Val = mochijson2:decode(Bin),    Response = call(ModFunBin, Val),    Json = mochijson2:encode(Response),    Req3 = cowboy_req:reply(200,                #{<<"content-type">> => <<"text/plain">>},                Json, Req2),    {ok, Req3, State};handle1(Path, Req, State) ->    Response = read_file(Path),    Req1 = cowboy_req:reply(200,                #{<<"content-type">> => <<"text/plain">>},                Response, Req),    {ok, Req1, State}.call([{<<"mod">>,MB},{<<"func">>,FB}], X) ->    Mod = list_to_atom(binary_to_list(MB)),    Func = list_to_atom(binary_to_list(FB)),    apply(Mod, Func, [X]).read_file(Path) ->    File = [$.|binary_to_list(Path)],    case file:read_file(File) of        {ok, Bin} -> Bin;        _ -> ["<pre>cannot read:", File, "</pre>"]    end.
键入make run启动服务器,然后在浏览器输入localhost:8080/test2.html就可以看到如下显示(没有下面的json文本),点击click显示json格式文本。



说明浏览器收到了来自Erlang发回的数据。

最后附上test2.html的内容:

<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script><h1>Test2</h1><button id="button1">click</button><div id="result"></div><script>$(document).ready(go);var data = {int:1234,            string:"abcd",            array:[1,2,3,'abc'],            map:{one:'abc', two:1, three:"abc"}};function go(){        $("#button1").click(test);}function test(){        $.ajax({url:"cgi?mod=echo&func=me",                type:'POST',                data:JSON.stringify(data),                success:function(str){                        var ret = JSON.parse(str);                        $("#result").html("<pre>"+                                          JSON.stringify(ret, undefined, 4) +                                          "</pre>");                }});}</script>

  

总结:模仿《Erlang程序设计(第二版)》上第25.4节“用cowboy构建嵌入式Web服务器”的内容,但书里的代码有一些已经过时了,在网上查了很多资料,也加深了自己对cowboy的理解。这个项目等于是更新了书里的echo服务器。希望能对大家有所帮助。


原创粉丝点击