mochiweb 源码阅读(六)
2012-07-20 00:45 rhinovirus 阅读(2058) 评论(2) 编辑 收藏 举报大家好,最近比较忙,游戏忙着上各个主流的大平台,事情比较多。还记得上次给大家推荐的Erlang的书吗?《Erlang/OTP并发编程实战》这本书在china-pub上已经有卖了,想学Erlang的朋友,可以买一本看看,地址:http://product.china-pub.com/3662181。一不小心又做广告了,呵呵,好书嘛,总是忍不住推荐给大家。
回到今天的正题,继续和大家分析mochiweb源码,在上一篇,我们总结了下mochiweb_example_deps 这个模块的作用,以及简单介绍了下mochiweb_example的启动。这一篇,我们详细看下启动过程。
首先,我们看下:mochiweb_example_web:start/1,代码如下:
start(Options) -> {DocRoot, Options1} = get_option(docroot, Options), Loop = fun (Req) -> ?MODULE:loop(Req, DocRoot) end, mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).
这里的参数是在 mochiweb_example_sup:web_specs/2 启动 mochiweb_example_web工作进程时传递过来的,也就是WebConfig,详细代码如下:
web_specs(Mod, Port) -> P = mochiweb_example_deps:local_path(["priv", "www"]), io:format("P = ~p~n", [P]), WebConfig = [{ip, {0,0,0,0}}, {port, Port}, {docroot, P}], {Mod, {Mod, start, [WebConfig]}, permanent, 5000, worker, dynamic}.
好了,知道了这个参数的值,我们继续回到 mochiweb_example_web:start/1 函数:
{DocRoot, Options1} = get_option(docroot, Options),这一行调用mochiweb_example_web:get_option/2,代码如下:
get_option(Option, Options) ->
{proplists:get_value(Option, Options), proplists:delete(Option, Options)}.
这里有2个系统函数,我们先看下:
函数:proplists:get_value/2,erlang doc地址:http://www.erlang.org/doc/man/proplists.html#get_value-2,如下图:
这个函数,相当于 get_value(Key, List, undefined),所以我们重点看下:proplists:get_value/3,从列表中返回值的一个简单的键/值属性。如果从List查找到Key,将返回{Key,Value},该函数返回相应的值,否则返回默认值。
函数:proplists:delete/2,从List中删除所有和Key相关的项。 erlang doc地址:www.erlang.org/doc/man/proplists.html#delete-2,如下图:
我们在shell上做些简单的测试,测试结果如下:
好了,弄清楚了mochiweb_example_web:get_option/2函数,我们继续回到mochiweb_example_web:start/1 函数,看如下代码:
Loop = fun (Req) -> ?MODULE:loop(Req, DocRoot) end,
这段代码也比较简单,定义个匿名函数,传递Req参数,匿名函数中就一行代码,调用本模块中的loop/2函数。这个函数我们先跳过,等真正运行该函数时,我们再回过头来看这个函数,这个函数代码如下:
loop(Req, DocRoot) -> "/" ++ Path = Req:get(path), try case Req:get(method) of Method when Method =:= 'GET'; Method =:= 'HEAD' -> case Path of _ -> Req:serve_file(Path, DocRoot) end; 'POST' -> case Path of _ -> Req:not_found() end; _ -> Req:respond({501, [], []}) end catch Type:What -> Report = ["web request failed", {path, Path}, {type, Type}, {what, What}, {trace, erlang:get_stacktrace()}], error_logger:error_report(Report), %% NOTE: mustache templates need \ because they are not awesome. Req:respond({500, [{"Content-Type", "text/plain"}], "request failed, sorry\n"}) end.
继续往下看 mochiweb_example_web:start/1 函数:
mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).
这里调用函数:mochiweb_http:start/1,传递一个列表,这个列表由三部分组成:
第一部分:{name, ?MODULE},?MODULE为当前模块名称;
第二部分:{loop, Loop},Loop为上一行代码定义的匿名函数;
第三部分:由第一行代码返回的元组中的第二个项,也就是:[{ip,{0,0,0,0}},{port,8080}]。
好了,弄清楚参数,我们就可以看下:mochiweb_http:start/1 函数,代码如下:
%% @spec start(Options) -> ServerRet %% Options = [option()] %% Option = {name, atom()} | {ip, string() | tuple()} | {backlog, integer()} %% | {nodelay, boolean()} | {acceptor_pool_size, integer()} %% | {ssl, boolean()} | {profile_fun, undefined | (Props) -> ok} %% | {link, false} %% @doc Start a mochiweb server. %% profile_fun is used to profile accept timing. %% After each accept, if defined, profile_fun is called with a proplist of a subset of the mochiweb_socket_server state and timing information. %% The proplist is as follows: [{name, Name}, {port, Port}, {active_sockets, ActiveSockets}, {timing, Timing}]. %% @end start(Options) -> mochiweb_socket_server:start(parse_options(Options)).
从注释来看,这个函数的作用是启动一个mochiweb服务器,关于Options参数的说明也很详细。
好了,这一篇就到这里,从下一篇开始我们将正式进入mochiweb源码。从这个函数来看,mochiweb源码还是比较工整的,代码注释也比较完善,感谢作者为我们奉献这么好的开源项目,来让我们学习。
最后,谢谢大家的耐心阅读。好梦。
本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名rhinovirus(包含链接http://www.cnblogs.com/rhinovirus/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系。