鸿 网 互 联 www.68idc.cn

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

Cowboy 源码分析(十七)

来源:互联网 作者:佚名 时间:2012-11-15 13:43
大家好,今天继续跟大家分享Cowboy,我发现最近有点慢,没有刚开始写的那么凶猛了,自己想了想:一个是时间上没办法保证了,另一个是自己有点散漫。得好好调整下,一定要坚持下去。游戏马上要上大平台了,最近版本多,事多,但这都不是理由,呵呵,时间就像

  大家好,香港服务器,今天继续跟大家分享Cowboy,我发现最近有点慢,没有刚开始写的那么凶猛了,自己想了想:一个是时间上没办法保证了,另一个是自己有点散漫。得好好调整下,一定要坚持下去。游戏马上要上大平台了,最近版本多,事多,但这都不是理由,呵呵,时间就像女人的乳沟,挤挤还是有的。所以到家,洗个澡,继续努力。好了,说的有点多了,回到正题。

  上一篇,我们在文章最后,留下了几个疑问,今天一并解决。

  首先是,当 erlang:decode_packet/3,这个函数返回 {ok, Header, Rest},而由于Header参数的值不同,将匹配 cowboy_http_protocol:header/3,函数的各个分支,我们整理下:

  第一个分支:

header({http_header, _I, 'Host', _R, RawHost}, Req=#http_req{ transport=Transport, host=undefined}, State) -> RawHost2 = cowboy_bstr:to_lower(RawHost), case catch cowboy_dispatcher:split_host(RawHost2) of {Host, RawHost3, undefined} -> Port = default_port(Transport:name()), parse_header(Req#http_req{ host=Host, raw_host=RawHost3, port=Port, headers=[{'Host', RawHost3}|Req#http_req.headers]}, State); {Host, RawHost3, Port} -> parse_header(Req#http_req{ host=Host, raw_host=RawHost3, port=Port, headers=[{'Host', RawHost3}|Req#http_req.headers]}, State); {'EXIT', _Reason} -> error_terminate(400, State) end;

  这个分支,Header参数的值为如下时,会调用这个分支:

  < Header = {http_header,14,'Host',undefined,<<"localhost:8080">>}

  < Rest = <<"User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n">>

  这个分支里的代码,我不再讲了,我在之前的Cowboy 源码分析(十二) 中详细讲解了,大家可以回忆下。  

  第二个分支:

header({http_header, _I, 'Host', _R, _V}, Req, State) -> parse_header(Req, State);

  这个分支在第一个分支后面,我们看下,其实这个分支,很简单的调用了cowboy_http_protocol:parse_header/2 函数,这个分支,好像没有用到,以后如果用到,我们再看吧。

  第三个分支:

header({http_header, _I, 'Connection', _R, Connection}, Req=#http_req{headers=Headers}, State=#state{ req_keepalive=Keepalive, max_keepalive=MaxKeepalive}) when Keepalive < MaxKeepalive -> Req2 = Req#http_req{headers=[{'Connection', Connection}|Headers]}, {ConnTokens, Req3} = cowboy_http_req:parse_header('Connection', Req2), ConnAtom = cowboy_http:connection_to_atom(ConnTokens), parse_header(Req3#http_req{connection=ConnAtom}, State);

  同样的,Header参数的值为如下时,会调用这个分支:

  < Header = {http_header,2,'Connection',undefined,<<"keep-alive">>}
  < Rest = <<"\r\n">>

  这个分支里的代码,我们也详细讲过,如果你还记得 Cowboy 源码分析(十三) 这一篇,我们很详细的讲解了这个方法。

  第四个分支:

header({http_header, _I, Field, _R, Value}, Req, State) -> Field2 = format_header(Field), parse_header(Req#http_req{headers=[{Field2, Value}|Req#http_req.headers]}, State);

  这个分支,Field,免备案空间,并不是常量,而是变量,我们可以发现,当Header参数的值为以下这些时,将调用这个分支:

  < Header = {http_header,24,'User-Agent',undefined,
                        <<"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0">>}
  < Rest = <<"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n">>

  < Header = {http_header,8,'Accept',undefined,
                        <<"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8">>}
  < Rest = <<"Accept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n">>

  < Header = {http_header,11,'Accept-Language',undefined,<<"en-us,en;q=0.5">>}
  < Rest = <<"Accept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n">>

  < Header = {http_header,10,'Accept-Encoding',undefined,<<"gzip, deflate">>}
  < Rest = <<"Connection: keep-alive\r\n\r\n">>

  我们之前没讲过这个分之,这里我们详细看下,这个分支,就2行代码,第二行,只是简单的修改了Req#http_req记录,就不讲了,重点看下第一行:

  Field2 = format_header(Field), 这一行,cowboy_http_protocol:format_header/1 函数如下:

网友评论
<