3、Nitrogen 是怎样处理路由(route)和操作请求(request)的
路由和请求,是Web服务器必须处理的2项基本任务。由项目模块,如quickstart.erl,规定处理方式:
route(Path) -> nitrogen:route(Path).
request(Module) -> nitrogen:request(Module).
首先看对“请求”的处理。在模块nitrogen.erl中,函数request/1:
request(_) -> ok.
可见,这个函数其实什么也不做。于是,在默认设置的条件下,来自客户端的请求,全部由nitrogen:route(Path)处理:
route(Path) -> wf_utils:path_to_module(Path).
好的,查看 wf_utils.erl:
path_to_module(undefined) -> {web_index, ""};
%% 如果Path匹配的是undefined,返回元组,即网站首页
path_to_module(S) ->
case lists:last(S) of
%% 列表和字符串是一回事。返回字符串S的末尾字符
$/ ->
%% 如果尾字符是整数47(ASCII码“/”)... 这里有点让我犯糊涂
S1 = S ++ "index",
%% 字符串尾附加"index"
tokens_to_module(string:tokens(S1, "/"), [], true);
%% string:tokens/2,相当于Python的S1.split('/')
_ ->
%% 如果尾字符是“_”...
tokens_to_module(string:tokens(S, "/"), [], false)
end.
tokens_to_module([], PathInfoAcc, AddedIndex) -> {web_404, to_path_info(PathInfoAcc, AddedIndex)};
%% 如果第一参数(分解成符号列表的Path)是空列表,返回网页错误信息
tokens_to_module(Tokens, PathInfoAcc, AddedIndex) ->
try
% Try to get the name of a module.
ModuleString = string:join(Tokens, "_"),
%% 若Token=["1","2","3"],则ModuleString="1_2_3"
Module = list_to_existing_atom(ModuleString),
%% 列表变原子。若ModuleString="index",则Module=index
% Moke sure the module is loaded. 第一个词应为Make,不该是Moke(驴)
code:ensure_loaded(Module),
{Module, to_path_info(PathInfoAcc, AddedIndex)}
catch _ : _ ->
% Strip off the last token, and try again.
LastToken = lists:last(Tokens),
Tokens1 = lists:reverse(tl(lists:reverse(Tokens))),
tokens_to_module(Tokens1, [LastToken|PathInfoAcc], AddedIndex)
end.
以上函数的用途,是把web路径转换成为模块名称。例如:
把web地址web/samples/effects转换成web_samples_effects。
模块web_samples_effects已经装载到内存中,它的源文件是web_samples_effects.erl。