Cowboy 源码分析(二十三)
2012-06-27 01:09 rhinovirus 阅读(1073) 评论(0) 编辑 收藏 举报大家好,上一篇在文章的最后我们提到cowboy_http_protocol:terminate_request/3 函数,今天我们继续往下看:
-spec terminate_request(any(), #http_req{}, #state{}) -> ok. terminate_request(HandlerState, Req, State) -> HandlerRes = handler_terminate(HandlerState, Req, State), next_request(Req, State, HandlerRes).
这个函数就两行代码:
首先调用cowboy_http_protocol:handler_terminate/3 函数:
-spec handler_terminate(any(), #http_req{}, #state{}) -> ok. handler_terminate(HandlerState, Req, #state{handler={Handler, Opts}}) -> try Handler:terminate(Req#http_req{resp_state=locked}, HandlerState) catch Class:Reason -> PLReq = lists:zip(record_info(fields, http_req), tl(tuple_to_list(Req))), error_logger:error_msg( "** Handler ~p terminating in terminate/2~n" " for the reason ~p:~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, HandlerState, PLReq, erlang:get_stacktrace()]) end.
Handler:terminate(Req#http_req{resp_state=locked}, HandlerState)
= default_handler:terminate(Req#http_req{resp_state=locked}, HandlerState)
跟之前类似,调用 default_handler:terminate/2 函数:
terminate(_Req, _State) ->
ok.
简单到不能再简单的函数,当函数正确执行时,返回ok,那么如果是执行函数中有异常,那么cowboy_http_protocol:handler_terminate/3 函数就会捕获到异常。
我们来做个测试,修改default_handler:terminate/2 函数,让它手动抛出异常,然后来跟踪下代码的执行过程,修改代码如下:
terminate(_Req, _State) -> throw("terminate error."), ok.
如上面所示,很简单,我们添加了一行代码,throw("terminate error."), 好了,重新编译,然后运行,这里我依然使用Debugger,来断点查看下,运行情况,如下图:
注意:
< Class = throw
< Reason = "terminate error."
接下来,我们看下异常处理的具体逻辑:
catch Class:Reason -> PLReq = lists:zip(record_info(fields, http_req), tl(tuple_to_list(Req))), error_logger:error_msg( "** Handler ~p terminating in terminate/2~n" " for the reason ~p:~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, HandlerState, PLReq, erlang:get_stacktrace()]) end.
这里有几个系统函数,我们之前没接触过,这里我们按照老规矩,我们来一个一个看下:
首先是 tuple_to_list/1 函数,这个函数比较常用,erlang doc地址:http://www.erlang.org/doc/man/erlang.html#tuple_to_list-1 从函数命名,应该很容易明白,就是将元组转成列表,下图是官方的解释,以及例子:
接下来是 tl/1 函数,返回去掉列表中第一个元素的列表,erlang doc地址:http://www.erlang.org/doc/man/erlang.html#tl-1 和上面一样,我截了个图,方便大家查看:
然后看下,record_info/2 函数参考坚强2002同学的文章:http://www.cnblogs.com/me-sa/archive/2012/05/22/erlang-code-snippet-2.html
下面是我写的测试代码:
大家看看,我想应该能够对这个函数有一定的理解了吧。
往后就是 lists:zip/2 函数,erlang doc地址:http://www.erlang.org/doc/man/lists.html#zip-2 从网上找的,关于 lists模块中的函数中文解释,地址:http://blog.csdn.net/zhangjingyangguang/article/details/7377787 谢谢这位朋友的翻译,下图是该函数的解释,很清楚:
最后是 error_logger:error_msg/2 函数,向错误日志发送一个错误消息。它的参数与io:format(Format, Data)函数的参数一样,erlang doc 地址:http://www.erlang.org/doc/man/error_logger.html#info_msg-2
最后是我们可以从Erlang的shell中看到的错误信息:
好了,这个函数就讲到这里。
下一篇,我们将从 cowboy_http_protocol:terminate_request/3 函数的这一行继续往下看:next_request(Req, State, HandlerRes).
最后,谢谢大家支持,晚安。
本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名rhinovirus(包含链接http://www.cnblogs.com/rhinovirus/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系。