0

I've taken the cowboy example code and brooken it.

The code for the default request handler looked like this:

-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.

its straight forward, but I wanted to make return files so I changed it to:

-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.

The try-catch thing should handle the fact that there might not be a file, but it does not. Why is that?

When I try to fetch a file that is not there I get a large error report in the console, can anyone tell me why?

=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}]}]
4

2 に答える 2

2

おそらくcatch句の評価方法が原因です。http: //www.erlang.org/doc/reference_manual/expressions.html#tryを参照してください。

Exprsの評価中に例外が発生したが、真のガードシーケンスを持つ正しいクラスのExceptionPatternが一致しない場合、Exprsがtry式で囲まれていないかのように例外が渡されます。

デフォルトであるthrowを検索しない場合は、エラークラス(error、throw、またはexit)を指定する必要があります。

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

キャッチオールエラーは次のように記述されます

catch
    _:_ -> 

クラスとExpressionPatternの両方を「ドントケア」として指定する方法に注意してください。

今までerlangに「手を出した」だけだったので、これがお役に立てば幸いです。:)

于 2012-06-15T13:19:04.440 に答える
1

This line:

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

Actually returns a list of binaries, like [<<"path">>,<<"path2">>] instead of something like "/path/path2" which should be what you're actually looking for.

So, to form the filesystem path:

{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),

(The badarg error you're getting is because the argument to file:read_file/1 is not a string (a list) but a list of binaries, which is not the expected argument.

And the catch needs a _:_ clause, just like Harald answer states.

Cheers.

于 2012-06-15T13:21:07.840 に答える