代码改变世界

Cowboy 源码分析(十)

2012-05-28 13:10  rhinovirus  阅读(2319)  评论(0编辑  收藏  举报

  在上一篇中,由于我对 erlang:decode_packet/3 方法的不理解,所以造成了对 cowboy_http_protocol:request/2 方法的困惑,这一篇,我将结合 erlang Debugger 工具 和 HttpFox 工具来看看,究竟是怎么回事。Debugger 我就不多说了,了解erlang的朋友,应该都知道这个工具,如果你是初学,没用过这个工具,可以参考我之前的一篇文章,使用 debugger 简单调试 erlang 简单介绍了这个工具。HttpFox An HTTP analyzer addon for Firefox,HttpFox monitors and analyzes all incoming and outgoing HTTP traffic between the browser and the web servers. 简单说,HttpFox 可以用来 抓取 HTTP 包。

  首先,启动 debugger:debugger:start(). 如果出现下图的界面,表示启动成功:

  

  接着,添加 cowboy_http_protocol 模块,并设置断点,如下图:  

  

  好了,接下来,我们启动 cowboy_examples:cowboy_examples:start(). 服务器启动完成,

  我们打开火狐,同时启动 HttpFox,访问 http://localhost:8080/ 如下图:

  

  同时,debugger会出现如下界面:

  

  我们点击 Next 往下走,当我们程序走到 cowboy_http_protocol:wait_request/1 时,我们就可以从调试器中,右下角的监视器中看到从Socket中读取的数据Data了,如下图:

  

  这个Data完整的数据如下:

  <<"GET / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n">>

  对比我们从 HttpFox 看到的数据,如下图:

  

  这里,我们发现,两者的内容是一模一样的,只不过 HttpFox 工具,把排版弄好看了,每一行的数据分开显示。

  我们继续往下走,看下 cowboy_http_protocol:parse_request/1 方法:

  

  我们从监视器可以看到, Buffer,Request,Rest 的值,分别如下:

  Rest = <<"Host: localhost:8080\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n">>
  Request = {http_request,'GET',{abs_path,<<"/">>},{1,1}}
  Buffer = <<"GET / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n">>

  现在来看,我们对 erlang:decode_packet(http_bin, Buffer, []) 这个方法,比以前是不是了解更多了,如果你觉得这样还不够,那么可以看下源码,欢迎大家跟我分享。

  知道了 Request 和 Rest 的值,我们就可以很好的了解 cowboy_http_protocol:request/2 方法:  

request({http_request, Method, {abs_path, AbsPath}, Version},
        State=#state{socket=Socket, transport=Transport,
        req_keepalive=Keepalive, max_keepalive=MaxKeepalive,
        onresponse=OnResponse, urldecode={URLDecFun, URLDecArg}=URLDec}) ->
    URLDecode = fun(Bin) -> URLDecFun(Bin, URLDecArg) end,
    {Path, RawPath, Qs} = cowboy_dispatcher:split_path(AbsPath, URLDecode),
    ConnAtom = if Keepalive < MaxKeepalive -> version_to_connection(Version);
        true -> close
    end,
    parse_header(#http_req{socket=Socket, transport=Transport,
        connection=ConnAtom, pid=self(), method=Method, version=Version,
        path=Path, raw_path=RawPath, raw_qs=Qs, onresponse=OnResponse,
        urldecode=URLDec}, State);

  我们可以从 debugger工具上看到,这些参数的值:

  

        

  好了,今天就到这,下一篇,我们将继续跟大家分享,接下来的代码,谢谢大家支持。