【问题标题】:Error reports in ErlangErlang 中的错误报告
【发布时间】:2012-06-18 12:57:02
【问题描述】:

我已经把牛仔示例代码弄坏了。

默认请求处理程序的代码如下所示:

-module(default_handler).
-behaviour(cowboy_http_handler).
-export([init/3, handle/2, terminate/2]).

init({_Any, http}, Req, []) ->
    {ok, Req, undefined}.

handle(Req, State) ->
    {ok, Req2} = cowboy_http_req:reply(200, [], <<"Hello world!">>, Req),
    {ok, Req2, State}.

terminate(_Req, _State) ->
    ok.

直截了当,但我想制作返回文件,所以我将其更改为:

-module(default_handler).
-behaviour(cowboy_http_handler).
-export([init/3, handle/2, terminate/2]).

init({_Any, http}, Req, []) ->
    {ok, Req, undefined}.

handle(Req, State) ->
    try 
    {Path, Req1} = cowboy_http_req:path(Req),
    {ok, File} = file:read_file(Path),
    cowboy_http_req:reply(200, [], File, Req1)
    of 
    {ok, Req2} ->
        {ok, Req2, State}
    catch
    _ -> 
        {ok, Req3} = cowboy_http_req:reply(200, [], <<"Hello world!">>, Req),
        {ok, Req3, State}
    end.

terminate(_Req, _State) ->
    ok.

try-catch 应该处理可能没有文件的事实,但它没有。这是为什么?

当我尝试获取一个不存在的文件时,我在控制台中收到一个很大的错误报告,谁能告诉我为什么?

=ERROR REPORT==== 15-Jun-2012::14:24:54 ===
** Handler default_handler terminating in handle/2
   for the reason error:{badmatch,{error,badarg}}
** Options were []
** Handler state was undefined
** Request was [{socket,#Port<0.1515>},
                {transport,cowboy_tcp_transport},
                {connection,keepalive},
                {pid,<0.1175.0>},
                {method,'GET'},
                {version,{1,1}},
                {peer,undefined},
                {host,[<<"localhost">>]},
                {host_info,undefined},
                {raw_host,<<"localhost">>},
                {port,8080},
                {path,[<<"favicon.ico">>]},
                {path_info,undefined},
                {raw_path,<<"/favicon.ico">>},
                {qs_vals,undefined},
                {raw_qs,<<>>},
                {bindings,[]},
                {headers,
                    [{'Accept-Charset',<<"ISO-8859-1,utf-8;q=0.7,*;q=0.3">>},
                     {'Accept-Language',<<"en-US,en;q=0.8">>},
                     {'Accept-Encoding',<<"gzip,deflate,sdch">>},
                     {'User-Agent',
                         <<"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/10.10 Chromium/18.0.1025.151 Chrome/18.0.1025.151 Safari/535.19">>},
                     {'Accept',<<"*/*">>},
                     {'Connection',<<"keep-alive">>},
                     {'Host',<<"localhost">>}]},
                {p_headers,[{'Connection',[<<"keep-alive">>]}]},
                {cookies,undefined},
                {meta,[]},
                {body_state,waiting},
                {buffer,<<>>},
                {resp_state,waiting},
                {resp_headers,[]},
                {resp_body,<<>>},
                {onresponse,undefined},
                {urldecode,{#Fun<cowboy_http.urldecode.2>,crash}}]
** Stacktrace: [{default_handler,handle,2,
                                 [{file,"src/default_handler.erl"},{line,13}]},
                {cowboy_http_protocol,handler_handle,3,
                                      [{file,"src/cowboy_http_protocol.erl"},
                                       {line,298}]}]

【问题讨论】:

    标签: erlang try-catch cowboy


    【解决方案1】:

    可能是因为它如何评估 catch 子句,请参阅 http://www.erlang.org/doc/reference_manual/expressions.html#try

    如果在 Expr 求值期间发生异常,但没有匹配的正确类的 ExceptionPattern 与真正的保护序列,则传递异常,就好像 Expr 没有包含在 try 表达式中一样。

    如果不查找默认值,则需要指定错误class(错误、抛出或退出),即 throw。

    try Exprs of
       Pattern1 [when GuardSeq1] ->
           Body1;
        ...;
       PatternN [when GuardSeqN] ->
            BodyN
    catch
        [Class1:]ExceptionPattern1 [when ExceptionGuardSeq1] ->
            ExceptionBody1;
        ...;
       [ClassN:]ExceptionPatternN [when ExceptionGuardSeqN] ->
            ExceptionBodyN
    

    a catch-all-errors 会写成

    catch
        _:_ -> 
    

    注意您如何将类和 ExpressionPattern 都指定为“不关心”。

    希望这会有所帮助,因为直到现在我才“涉足”erlang。 :)

    【讨论】:

    • 不 [] 表示在这种情况下 Class 是可选的吗?
    • 确实如此,但如果你省略类 erlang 假定它是 throw
    【解决方案2】:

    这一行:

    {Path, Req1} = cowboy_http_req:path(Req),
    

    实际上返回一个二进制文件列表,例如 [>,>] 而不是像 "/path/path2" 之类的东西,这应该是您真正要查找的内容。

    所以,形成文件系统路径:

    {Path, Req1} = cowboy_http_req:path(Req),
    FsPath = lists:foldl(
        fun(PathComponent, Acc) ->
            string:join([Acc, erlang:binary_to_list(PathComponent)], "/")
        end,
        "",
        Path
    ),
    {ok, File} = file:read_file(FsPath),
    

    (您收到的 badarg 错误是因为 file:read_file/1 的参数不是字符串(列表)而是二进制文件列表,这不是预期的参数。

    而 catch 需要一个 _:_ 子句,就像 Harald 的回答所说的那样。

    干杯。

    【讨论】:

    • : 不是可选的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    相关资源
    最近更新 更多