debuggingerlangwebmachine

Debugging Erlang Webmachine resource functions


I'm trying to learn how to write Erlang Webmachine resources. One resource throws an error, but I can't tracking it down. The error message in the crash report does not provide enough information.

Is there a way to test these functions in the Erlang shell?

Most of the functions in the resource require request and context parameters. But I don't know how to simulate these parameters in the browser.

Example code below.

Thanks,

LRP

Example code:

I'm thinking specifically of functions like:

content_types_provided(RD, Ctx) ->
   Path = wrq:disp_path(RD),
   {[{webmachine_util:guess_mime(Path), generate_body}],
   RD, Ctx}.

But my current bug is in the init function.

This works...

Dispatch rule:

{["blip"], zzz_resource, []}.

Init:

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

to_html(ReqData, State) ->
    % {"<html><bodoy>Hello, new world</body></html>", ReqData, State}.
        {test:test(), ReqData, State}.

But this throws an error:

Dispatch:

{["static"], static_resource,[]}.

Init:

init(_) ->
   DocRoot =
       case init:get_argument(doc_root) of
          {ok, [[DR]]} -> DR;
           error -> "doc_root path error"
       end,
   {ok, #ctx{docroot=DocRoot}}.

=ERROR REPORT==== 4-Aug-2011::10:54:56 ===
webmachine error: path="/static"
{error,function_clause,
   [{filename,join,[[]]},
    {static_resource,resource_exists,2},

Solution

  • There are a lot of layers to this answer depending on what you want to see and how deep down the rabbit hole you want to go.


    Let's start with the easy stuff:

    The error you are getting tells me that a call to static_resource:resource_exists/2 resulted in a call to filename:join/1 which failed because it was passed [] as its argument. That should help you track down the issue.

    Recommended reading: errors-and-exceptions


    A crude way to track down errors in any language is just to add print statements at strategic loctations. In this case you can use io:format/2 or erlang:display/1 to display whatever you want to the console. For example:

    ...
    erlang:display("I'm inside resource_exists!"),
    StuffToJoin = ["foo", "bar"],
    erlang:display(StuffToJoin),
    filename:join(StuffToJoin),
    ...
    

    Just reload the page you should see the value printed in the console (assuming the appropriate function was called as part of the reload).


    If you want to manually test a resource (like in a unit test) you can do something like the following:

    Headers = [{"Host", "mydomain.com"}, {"user-agent", "Firefox"}],
    Context = [],
    Path = "/static",
    ReqData = wrq:create('GET', {1,1}, Path, mochiweb_headers:from_list(Headers)),
    static_resource:resource_exists(ReqData, Context)
    

    If you want a deep look at how to debug webmachine, you can read this. You can get pretty far with the above, but doing a full trace can be helpful if you need to see the decision graph.