热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Cowboy源码分析(十一)

上一篇,我们使用debugger和HttpFox很方便了,查看了方法中的变量,不得不说,debugger断点调试还是比较好用

  上一篇,我们使用debugger和HttpFox很方便了,查看了方法中的变量,不得不说,debugger 断点调试还是比较好用的。这一篇,我们仍将使用这些工具来帮助我们了解代码,好了,接着上一篇继续来看 cowboy_http_protocol:request/2 方法:

  

  

  上面两张图,是我们上一篇文章,我们看到的函数,以及变量的值,这一篇,我们继续来看下这个函数:

  URLDecode = fun(Bin) -> URLDecFun(Bin, URLDecArg) end,定义了一个匿名函数,Bin是匿名函数定义的变量,我们看下 URLDecFun 这个变量,

  urldecode={URLDecFun, URLDecArg}=URLDec

  还记得 #state{} 在 cowboy_http_protocol:init/4 方法中,urldecode 的定义吗?我截了个图,方便大家回忆,从下面图,我们可以很清楚看到 urldecode 的值:

  那么 urldecode={URLDecFun, URLDecArg}=URLDec 自然就是 urldecode={fun cowboy_http:urldecode/2, crash}=URLDec。

  

  弄明白了这几个参数,我们继续往下看:

  {Path, RawPath, Qs} = cowboy_dispatcher:split_path(AbsPath, URLDecode),  看下 cowboy_dispatcher:split_path/2 这个函数:

%% @doc Split a path into a list of path segments.
%%
%%
Following RFC2396, this function may return path segments containing any
%%
character, including / if, and only if, a / was escaped
%%
and part of a path segment.
-spec split_path(binary(), fun((binary()) -> binary())) ->{tokens(), binary(), binary()}.
split_path(Path, URLDec)
->case binary:split(Path, <<"?">>) of[Path] -> {do_split_path(Path, <<"/">>, URLDec), Path, <<>>};[<<>>, Qs] -> {[], <<>>, Qs};[Path2, Qs] -> {do_split_path(Path2, <<"/">>, URLDec), Path2, Qs}end.-spec do_split_path(binary(), <<_:8>>, fun((binary()) -> binary())) -> tokens().
do_split_path(RawPath, Separator, URLDec)
->EncodedPath &#61; case binary:split(RawPath, Separator, [global, trim]) of[<<>>|Path] -> Path;Path -> Pathend,[URLDec(Token) || Token <- EncodedPath].

  函数的注释意思为&#xff1a;分割路径中的参数成为一个列表。我们看下  case binary:split(Path, <<"?">>) of 这行&#xff0c;这个函数第一次遇到&#xff0c;同样查下erlang doc&#xff1a;http://www.erlang.org/doc/man/binary.html#split-2 比较简单&#xff0c;就是按照第二个参数&#xff0c;分割第一个参数&#xff0c;返回分割后的列表。在这里 Path &#61; <<"/">> &#xff0c;那么分割后为 [<<"/">>]。

  往下看 cowboy_dispatcher:do_split_path/3 这个函数&#xff0c;同样用到了 binary:split/3 函数&#xff0c;只不过这次是三个参数&#xff0c;如果你认真看了上面我给出的 erlang doc 链接&#xff0c;你应该能知道 binary:split/2 其实调用了 binary:split/3&#xff0c;只不过最后一个参数是 []。那么我们看下这次出现的第三个参数是什么意思呢&#xff1f;下面是erlang doc 给出的说明&#xff1a;

trim

Removes trailing empty parts of the result (as does trim in re:split/3)

移除结果中尾部为空的部分。

global

Repeats the split until the Subject is exhausted. Conceptually the global option makes split work on the positions returned by matches/3, while it normally works on the position returned by match/3.

重复分隔直到不能按Pattern项分割Subject

  好了&#xff0c;弄清楚这2个参数的意思&#xff0c;我们就知道结果&#xff1a;

  EncodedPath &#61; case binary:split(RawPath, Separator, [global, trim]) of

  EncodedPath &#61; case binary:split(<<"/">>, <<"/">>, [global, trim]) of

  EncodedPath &#61;  []

  接下来看下&#xff1a;[URLDec(Token) || Token <- EncodedPath]. 这里是一个列表解析&#xff0c;URLDec &#61; URLDecode &#61; fun(Bin) -> URLDecFun(Bin, URLDecArg) end.

  这里依次对 EncodedPath列表中的元素&#xff0c;依次调用 URLDec(Token)&#xff0c;然后返回每个调用后的结果组成的列表。

  这边我把 cowboy_http:urldecode/2 方法贴下下面&#xff0c;我并不打算去解释这个方法&#xff0c;大家详细看下&#xff0c;其实这个方法很简单&#xff0c;就是对 URL 中的参数解码&#xff1a;

%% &#64;doc Decode a URL encoded binary.
%%
&#64;equiv urldecode(Bin, crash)
-spec urldecode(binary()) -> binary().
urldecode(Bin)
when is_binary(Bin) ->urldecode(Bin, <<>>, crash).%% &#64;doc Decode a URL encoded binary.
%%
The second argument specifies how to handle percent characters that are not
%%
followed by two valid hex characters. Use &#96;skip&#39; to ignore such errors,
%%
if &#96;crash&#39; is used the function will fail with the reason &#96;badarg&#39;.
-spec urldecode(binary(), crash | skip) -> binary().
urldecode(Bin, OnError)
when is_binary(Bin) ->urldecode(Bin, <<>>, OnError).-spec urldecode(binary(), binary(), crash | skip) -> binary().
urldecode(
<<$%, H, L, Rest/binary>>, Acc, OnError) ->G &#61; unhex(H),M &#61; unhex(L),if G &#61;:&#61; error; M &#61;:&#61; error ->case OnError of skip -> ok; crash -> erlang:error(badarg) end,urldecode(<>, <>, OnError);true ->urldecode(Rest, <bsl 4 bor M)>>, OnError)end;
urldecode(
<<$%, Rest/binary>>, Acc, OnError) ->case OnError of skip -> ok; crash -> erlang:error(badarg) end,urldecode(Rest, <>, OnError);
urldecode(
<<$&#43;, Rest/binary>>, Acc, OnError) ->urldecode(Rest, <>, OnError);
urldecode(
<>, Acc, OnError) ->urldecode(Rest, <>, OnError);
urldecode(
<<>>, Acc, _OnError) ->Acc.

  又跑了老远&#xff0c;回到 cowboy_dispatcher:split_path/2&#xff0c;最后返回 {[], <<"/">>, <<>>};

  接着&#xff0c;我们回到 cowboy_http_protocol:request/2 方法&#xff0c;看下这一行&#xff1a;

  {Path, RawPath, Qs} &#61; cowboy_dispatcher:split_path(AbsPath, URLDecode), 可以得到下面几个参数的值为&#xff1a;

  Qs &#61; <<>>
  Path &#61; []
  RawPath &#61; <<"/">>

  继续往下&#xff1a;

  ConnAtom &#61;

    if Keepalive

      version_to_connection(Version);
      true -> close
    end,

  下面是 cowboy_http_protocol:version_to_connection/1 函数&#xff1a;

-spec version_to_connection(cowboy_http:version()) -> keepalive | close.
version_to_connection({
1, 1}) -> keepalive;
version_to_connection(_Any)
-> close.

  这段代码主要是判断 同时和服务器保持连接。而我们看下 HTTP 关于Keep-Alive的介绍&#xff1a;使客户端到服务器端的连接持续有效&#xff0c;当出现对服务器的后继请求时&#xff0c;Keep-Alive功能避免了建立或者重新建立连接。如果暂时不理解&#xff0c;没关系&#xff0c;先跳过&#xff0c;以后我还会回过头来整体介绍。

  再往下&#xff1a;

  parse_header(#http_req{socket&#61;Socket, transport&#61;Transport, connection&#61;ConnAtom, pid&#61;self(), method&#61;Method, version&#61;Version, path&#61;&#39;*&#39;, raw_path&#61; <<"*">>, raw_qs&#61; <<>>, onresponse&#61;OnResponse, urldecode&#61;URLDec}, State);

   这行是解析 HTTP 头部&#xff0c;我们将在下一篇继续和大家分享接下来的代码&#xff0c;谢谢大家支持。

转:https://www.cnblogs.com/yourihua/archive/2012/05/29/2522196.html



推荐阅读
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 在编写业务代码时,常常会遇到复杂的业务逻辑导致代码冗长混乱的情况。为了解决这个问题,可以利用中间件模式来简化代码逻辑。中间件模式可以帮助我们更好地设计架构和代码,提高代码质量。本文介绍了中间件模式的基本概念和用法。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
author-avatar
熙8778_565
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有