热门标签 | 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



推荐阅读
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 在Delphi7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本。定义如下:1234 ... [详细]
  • 2022年7月20日:关键数据与市场动态分析
    2022年7月20日,本文对当日的关键数据和市场动态进行了深入分析。主要内容包括:1. 关键数据的解读与趋势分析;2. 市场动态的变化及其对投资策略的影响;3. 相关经济指标的评估。通过这些分析,帮助读者更好地理解当前市场环境,为决策提供参考。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文全面解析了 Python 中字符串处理的常用操作与技巧。首先介绍了如何通过 `s.strip()`, `s.lstrip()` 和 `s.rstrip()` 方法去除字符串中的空格和特殊符号。接着,详细讲解了字符串复制的方法,包括使用 `sStr1 = sStr2` 进行简单的赋值复制。此外,还探讨了字符串连接、分割、替换等高级操作,并提供了丰富的示例代码,帮助读者深入理解和掌握这些实用技巧。 ... [详细]
  • 在PHP中,高效地分割字符串是一项常见的需求。本文探讨了多种技术,用于在特定字符(如“或”)后进行字符串分割。通过使用正则表达式和内置函数,可以实现更加灵活和高效的字符串处理。例如,可以使用 `preg_split` 函数来实现这一目标,该函数允许指定复杂的分隔符模式,从而提高代码的可读性和性能。此外,文章还介绍了如何优化分割操作以减少内存消耗和提高执行速度。 ... [详细]
  • PHP预处理常量详解:如何定义与使用常量 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • 本文详细介绍了如何使用Python中的smtplib库来发送带有附件的邮件,并提供了完整的代码示例。作者:多测师_王sir,时间:2020年5月20日 17:24,微信:15367499889,公司:上海多测师信息有限公司。 ... [详细]
  • php更新数据库字段的函数是,php更新数据库字段的函数是 ... [详细]
  • 本文总结了JavaScript的核心知识点和实用技巧,涵盖了变量声明、DOM操作、事件处理等重要方面。例如,通过`event.srcElement`获取触发事件的元素,并使用`alert`显示其HTML结构;利用`innerText`和`innerHTML`属性分别设置和获取文本内容及HTML内容。此外,还介绍了如何在表单中动态生成和操作``元素,以便更好地处理用户输入。这些技巧对于提升前端开发效率和代码质量具有重要意义。 ... [详细]
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社区 版权所有