博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mochiweb 源码阅读(十六)
阅读量:5218 次
发布时间:2019-06-14

本文共 3856 字,大约阅读时间需要 12 分钟。

  大家好,几天没跟新这个系列了,忙着考驾照,今天继续来跟大家分享mochiweb源码,上一篇我们讲到了mochiweb_http:handle_invalid_request/1函数,这一篇,我们来看下,正确的逻辑处理,再讲这之前,还有个地方跟大家提下,就是如果mochiweb_http:request/2函数,在使用receive读取消息时,如果发生超时,则是简单的关闭套接字以及退出进程,代码如下:

after ?REQUEST_RECV_TIMEOUT ->        mochiweb_socket:close(Socket),        exit(normal)    end.

  宏定义如下:

-define(REQUEST_RECV_TIMEOUT, 300000).   %% timeout waiting for request line

  好了,现在我们可以回到正确逻辑了:

{Protocol, _, {http_request, Method, Path, Version}} when Protocol == http orelse Protocol == ssl ->            ok = mochiweb_socket:setopts(Socket, [{packet, httph}]),            headers(Socket, {Method, Path, Version}, [], Body, 0);

  这个分支也只有2行代码,很简单,首先调用mochiweb_socket:setopts/2设置Socket选项,这里是:{packet, httph},当设置这个选项时,返回的数据包会是什么样的呢?通过查阅erlang doc,地址:,如下图:

  大致翻译如下:

    这两类往往是没有必要的,socket内部的第一行被读取后,将自动从http/http_bin切换到httph/httph_bin。无论如何,有些场合可能他们是有用的,例如从区块解析数据报。

  关于这个选项,还有如下一段描述:

  大致翻译如下:

    超文本传输协议。数据包返回的格式根据上述HttpPacket。一个包可以是一个请求,响应,一个头或端头标记。无效行返回HttpError

    确认请求的方法和报头域返回原子。其他返回作为字符串。

    当预计一个HttpRequest或者一个HttpResponsehttp协议类型应该只用于第一行。

    下面的调用应该使用httph得到HttpHeaderhttp_eoh返回结束的标志头并开始任何以下消息体。

    该变种http_bin和httph_bin将返回字符串(httpstring)为二进制文件代替列表。

  好了,现在我们已经大概知道了http | httph | http_bin | httph_bin这四个选项在什么情况下使用,回到mochiweb_http:request/2函数,设置完{packet, httph}后,紧接着调用mochiweb_http:headers/5函数:

headers(Socket, Request, Headers, _Body, ?MAX_HEADERS) ->    %% Too many headers sent, bad request.    ok = mochiweb_socket:setopts(Socket, [{packet, raw}]),    handle_invalid_request(Socket, Request, Headers);headers(Socket, Request, Headers, Body, HeaderCount) ->    ok = mochiweb_socket:setopts(Socket, [{active, once}]),    receive        {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);        {tcp_closed, _} ->            mochiweb_socket:close(Socket),            exit(normal);        _Other ->            handle_invalid_request(Socket, Request, Headers)    after ?HEADERS_RECV_TIMEOUT ->        mochiweb_socket:close(Socket),        exit(normal)    end.

  这个函数有两个分支,我们先看第一个,当HeaderCount为?MAX_HEADERS时,调用第一个分支,注释:Too many headers sent, bad request,发送太多的头部,坏的请求。

宏定义如下:

-define(MAX_HEADERS, 1000).

  其实这也很好理解,递归调用mochiweb_http:headers/5函数来解析http_header,直到解析到http_eoh为止,如果HeaderCount等于?MAX_HEADERS,则会走第一个分支,从这一行我们知道这个参数会在整个调用过程递增:

{Protocol, _, {http_header, _, Name, _, Value}} when Protocol == http orelse Protocol == ssl ->            headers(Socket, Request, [{Name, Value} | Headers], Body,                    1 + HeaderCount);

  第一个分支的逻辑,修改Socket选项{packet, raw},然后调用函数:mochiweb_http:handle_invalid_request/3处理为无效请求。

  第二个分支和前一篇介绍的mochiweb_http:request/2函数,有很多相同的地方,依然是修改Socket选项为{active, once},接着使用receive读取一条消息:

  消息格式说明:

  {http, Socket, HttpPacket}

  HttpPacket = HttpHeader | http_eoh

  HttpHeader = {http_header, integer(), HttpField, Reserved=term(), Value=HttpString}

  只要不是返回{http, Socket, http_eoh}就递归调用mochiweb_http:headers/5函数继续解析头部,并且保存{Name, Value}到Headers列表头部:

headers(Socket, Request, [{Name, Value} | Headers], Body,                    1 + HeaderCount);

  而当解析得到{http, Socket, http_eoh}时,处理如下:

{Protocol, _, http_eoh} when Protocol == http orelse Protocol == ssl ->            Req = new_request(Socket, Request, Headers),            call_body(Body, Req),            ?MODULE:after_response(Body, Req);

  这里就三行代码,首先调用mochiweb_http:new_request/3获取Req对象,接着调用mochiweb_http:call_body/2函数,最后调用该模块下的?MODULE:after_response/2函数。

  好了,这一篇就到这里,下一篇我们将继续从这三个函数来和大家分享。

  最后,谢谢大家的支持,晚安。

 

转载于:https://www.cnblogs.com/yourihua/archive/2012/08/06/2625806.html

你可能感兴趣的文章
Maven学习:项目之间的关系
查看>>
SQL查询总结 - wanglei
查看>>
安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
查看>>
20170817上课笔记
查看>>
makefile中使用变量
查看>>
GIT笔记:将项目发布到码云
查看>>
JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
查看>>
JavaScript 鸭子模型
查看>>
PHP典型功能与Laravel5框架开发学习笔记
查看>>
SQL Server 如何查询表定义的列和索引信息
查看>>
项目上传到github上
查看>>
GCD 之线程死锁
查看>>
NoSQL数据库常见分类
查看>>
JS小工具_字符串转16进制数组_02
查看>>
信息安全系统设计基础实验四—20135214万子惠20135227黄晓妍
查看>>
一题多解 之 Bat
查看>>
多次向文件结尾写入数据
查看>>
读书印记 - 《反脆弱》
查看>>
LAMP环境搭建
查看>>
puppet安装配置及使用
查看>>