鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > erlang > >

mochiweb 源码阅读(十七)

来源:互联网 作者:佚名 时间:2012-11-15 13:37
大家好,今天周五,继续来和大家一起分享mochiweb源码。最近我也是在看百度连城翻译的《Erlang/OTP并发编程实战》,其中第11章:为缓存添加HTTP接口,有这本书的朋友可以翻看下,这里介绍的内容,有助于大家理解mochiweb源码。 上一篇,我们讲到了 mochiweb_

  大家好,美国服务器,今天周五,继续来和大家一起分享mochiweb源码。最近我也是在看百度连城翻译的《Erlang/OTP并发编程实战》,其中第11章:为缓存添加HTTP接口,有这本书的朋友可以翻看下,这里介绍的内容,有助于大家理解mochiweb源码。

  上一篇,我们讲到了mochiweb_http:headers/5函数,当所有协议头解析完毕后会有一个空行,它标志着报文头部的结束,剩下的便是消息正文。

{Protocol, _, http_eoh} when Protocol == http orelse Protocol == ssl -> Req = new_request(Socket, Request, Headers), call_body(Body, Req), ?MODULE:after_response(Body, Req); {Protocol, _, {http_header, _, Name, _, Value}} when Protocol == http orelse Protocol == ssl -> headers(Socket, Request, [{Name, Value} | Headers], Body, 1 + HeaderCount);

  代码中第一个分支就是当读取到空行时,虚拟主机,继续处理消息正文,第二个分支则是解析每一个协议头。

  接下来我们首先看下:mochiweb_http:new_request/3函数:

new_request(Socket, Request, RevHeaders) -> ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), mochiweb:new_request({Socket, Request, lists:reverse(RevHeaders)}).

  这个函数首先修改socket选项{packet, raw},不设置消息打包规则,如果{packet, 1|2|4},则表示每一个包都会带上一个N(1,2或4)字节长的长度计数。

  该函数接着调用mochiweb:new_request/1函数:

%% @spec new_request({Socket, Request, Headers}) -> MochiWebRequest %% @doc Return a mochiweb_request data structure. new_request({Socket, {Method, {abs_path, Uri}, Version}, Headers}) -> mochiweb_request:new(Socket, Method, Uri, Version, mochiweb_headers:make(Headers)); % this case probably doesn't "exist". new_request({Socket, {Method, {absoluteURI, _Protocol, _Host, _Port, Uri}, Version}, Headers}) -> mochiweb_request:new(Socket, Method, Uri, Version, mochiweb_headers:make(Headers)); %% Request-URI is "*" %%new_request({Socket, {Method, '*'=Uri, Version}, Headers}) -> mochiweb_request:new(Socket, Method, Uri, Version, mochiweb_headers:make(Headers)).

  这个函数一共有三个分支,但是每一个都是匹配对应的参数,紧接着调用mochiweb_request:new/5函数,香港服务器租用,但是这里注意,我在mochiweb_request模块导出的函数列表中,并没有发现对应的函数,那么这究竟是怎么回事呢?

  这种用法称之为:参数化的Module(Parameterized Module),下面是关于这个用法的相关文章:

  

  

  %E5%8F%82%E6%95%B0%E5%8C%96%E7%9A%84module/

  

  这里注意mochiweb_request模块定义:

-module(mochiweb_request, [Socket, Method, RawPath, Version, Headers]).

  关于这个用法,希望大家认真看下上面几篇文章,就能够明白了。

  这里我们还需要看下:mochiweb_headers:make/1函数:

%% @spec make(headers() | [{key(), value()}]) -> headers() %% @doc Construct a headers() from the given list. make(L) when is_list(L) -> from_list(L); %% assume a non-list is already mochiweb_headers. make(T) -> T.

  如果L为列表,则调用函数mochiweb_headers:from_list/1函数:

%% @spec from_list([{key(), value()}]) -> headers() %% @doc Construct a headers() from the given list. from_list(List) -> lists:foldl(fun ({K, V}, T) -> insert(K, V, T) end, empty(), List).

  mochiweb_headers:empty/0函数

%% @type headers(). %% @type key() = atom() | binary() | string(). %% %% @doc Create an empty headers structure. empty() -> gb_trees:empty().

  mochiweb_headers:insert/3函数

%% @spec insert(key(), value(), headers()) -> headers() %% @doc Insert the pair into the headers, merging with any pre-existing key. %% A merge is done with Value = V0 ++ ", " ++ V1. insert(K, V, T) -> K1 = normalize(K), V1 = any_to_list(V), try gb_trees:insert(K1, {K, V1}, T) catch error:{key_exists, _} -> {K0, V0} = gb_trees:get(K1, T), V2 = merge(K1, V1, V0), gb_trees:update(K1, {K0, V2}, T) end.

  mochiweb_headers:normalize/1函数

normalize(K) when is_list(K) -> string:to_lower(K); normalize(K) when is_atom(K) -> normalize(atom_to_list(K)); normalize(K) when is_binary(K) -> normalize(binary_to_list(K)).

  mochiweb_headers:any_to_list/1函数

网友评论
<