Commits

Anonymous committed 8c30e7d

mixup

Comments (0)

Files changed (7)

BigHTTPGraph.wiki

-This diagram is illustrative of the flow of processing that a [[WebmachineResources|webmachine resource]] goes through from inception to response.
-
-Version 1 of this diagram, from Alan Dean, was the inspiration for webmachine_decision_core. Versions 2 and 3 were created in collaboration between Alan Dean and Justin Sheehy.
-
-A copy of v3 is found in the webmachine source tree for convenience. 
-
-{{http://bytebucket.org/justin/webmachine/wiki/http-headers-status-v3.png|http diagram v3}}
+This diagram is illustrative of the flow of processing that a [[WebmachineResources|webmachine resource]] goes through from inception to response.
+
+Version 1 of this diagram, from Alan Dean, was the inspiration for webmachine_decision_core. Versions 2 and 3 were created in collaboration between Alan Dean and Justin Sheehy.
+
+A copy of v3 is found in the webmachine source tree for convenience. 
+
+{{http://bytebucket.org/justin/webmachine/wiki/http-headers-status-v3.png|http diagram v3}}
+

DispatchConfiguration.wiki

 Any atom pathterms that were used in a match will cause a binding in the path_info element of the request's [[WebmachineReqData|ReqData]]. (if there was a foo atom that matched the token "bar", then {{{ wrq:get_path_info(foo, ReqData) }}} will return {{{ "bar" }}} inside the resource calls) If there was a star pathterm in the pathspec, then {{{ wrq:disp_path(ReqData) }}} in a resource function will return the URI portion that was matched by the star.
 
 The {{{ resource }}} is an atom identifying a [[WebmachineResources|resource]] that should handle a matching request. It will have the {{{ args }}} (which must be a list) passed to its init function before request handling begins. 
+
+

ExampleResources.wiki

-The simplest possible example is the one produced via the [[QuickStart]].
-
-For an example of a read/write filesystem server showing several interesting features and supporting GET, PUT, DELETE, and POST, see [[FixThisLink|demo_fs_resource].
-
-For a very simple resource demonstrating content negotiation, basic auth, and some caching headers, see [[FixThisLink|webmachine_demo_resource]].
-
-Some example code based on webmachine_demo_resource follows.
-
-The simplest working resource could export only one function in addition to init/1:
-
-{{{
-#!erlang
--module(webmachine_demo_resource).
--export([init/1, to_html/2]).
--include_lib("webmachine/include/webmachine.hrl").
-
-init([]) -> {ok, undefined}.
-
-to_html(ReqData, Context) -> {"<html><body>Hello, new world</body></html>", ReqData, Context}.
-}}}
-
-That's really it -- a working webmachine resource. That resource will respond to all valid GET requests with the exact same response.
-
-Many interesting bits of HTTP are handled automatically by Webmachine. For instance, if a client sends a request to that trivial resource with an Accept header that does not allow for a text/html response, they will receive a 406 Not Acceptable.
-
-Suppose I wanted to serve a plaintext client as well. I could note that I provide more than just HTML:
-
-{{{
-#!erlang
-content_types_provided(ReqData, Context) ->
-   {[{"text/html", to_html},{"text/plain",to_text}], ReqData, Context}.
-}}}
-
-I already have my HTML representation produced, so I add a text one:
-(and while I'm at it, I'll show that it's trivial to produce dynamic content as well)
-
-{{{
-#!erlang
-to_text(ReqData, Context) ->
-    Path = wrq:disp_path(ReqData),
-    Body = io_lib:format("Hello ~s from webmachine.~n", [Path]),
-    {Body, ReqData, Context}.
-}}}
-
-Now that this resource provides multiple media types, it automatically performs conneg:
-
-{{{
-$ telnet localhost 8000
-Trying 127.0.0.1...
-Connected to localhost.
-Escape character is '^]'.
-GET /demo/a/resource/path HTTP/1.1
-Accept: text/plain
-
-HTTP/1.1 200 OK
-Vary: Accept
-Server: MochiWeb/1.1 WebMachine/0.97
-Date: Sun, 15 Mar 2009 02:54:02 GMT
-Content-Type: text/plain
-Content-Length: 39
-
-Hello a/resource/path from webmachine.
-}}}
-
-What about authorization? Webmachine resources default to assuming the client is authorized, but that can easily be overridden. Here's an overly simplistic but illustrative example:
-
-{{{
-#!erlang
-is_authorized(ReqData, Context) ->
-    case wrq:disp_path(ReqData) of
-        "authdemo" -> 
-            case wrq:get_req_header("authorization", ReqData) of
-                "Basic "++Base64 ->
-                    Str = base64:mime_decode_to_string(Base64),
-                    case string:tokens(Str, ":") of
-                        ["authdemo", "demo1"] ->
-                            {true, ReqData, Context};
-                        _ ->
-                            {"Basic realm=webmachine", ReqData, Context}
-                    end;
-                _ ->
-                    {"Basic realm=webmachine", ReqData, Context}
-            end;
-        _ -> {true, ReqData, Context}
-    end.
-}}}
-
-With that function in the resource, all paths except {{{ /authdemo }}} from this resource's root are authorized. For that one path, the UA will be asked to do basic authorization with the user/pass of authdemo/demo1. It should go without saying that this isn't quite the same function that we use in our real apps, but it is nice and simple.
-
-To see that it works, you can point your browser at {{{ http://localhost:8000/demo/authdemo }}} with the demo app running:
-
-{{{
-$ curl -v http://localhost:8000/demo/authdemo
-> GET /demo/authdemo HTTP/1.1
-> Host: localhost:8000
-> Accept: */*
-> 
-< HTTP/1.1 401 Unauthorized
-< WWW-Authenticate: Basic realm=webmachine
-< Server: MochiWeb/1.1 WebMachine/0.97
-< Date: Sun, 15 Mar 2009 02:57:43 GMT
-< Content-Length: 0
-< 
-}}}
-{{{
-$ curl -v -u authdemo:demo1 http://localhost:8000/demo/authdemo 
-* Server auth using Basic with user 'authdemo'
-> GET /demo/authdemo HTTP/1.1
-> Authorization: Basic YXV0aGRlbW86ZGVtbzE=
-> Host: localhost:8000
-> Accept: */*
-> 
-< HTTP/1.1 200 OK
-< Vary: Accept
-< Server: MochiWeb/1.1 WebMachine/0.97
-< Date: Sun, 15 Mar 2009 02:59:02 GMT
-< Content-Type: text/html
-< Content-Length: 59
-< 
-<html><body>Hello authdemo from webmachine.
-</body></html>
-}}}
-
-HTTP caching support is also quite easy, with functions allowing resources to define (e.g.) {{{ last_modified }}} , {{{ expires }}}, and {{{ generate_etag.}}} For instance, since representations of this resource vary only by URI Path, I could use an extremely simple entity tag unfit for most real applications but sufficient for this example:
-
-{{{
-#!erlang
-generate_etag(ReqData, Context) -> {wrq:raw_path(ReqData), ReqData, Context}.
-}}}
-
-Similarly, here's a trivial expires rule:
-
-{{{
-#!erlang
-expires(ReqData, Context) -> {{{2021,1,1},{0,0,0}}, ReqData, Context}.
-}}}
-
-And now the response from our earlier request is appropriately tagged:
-
-{{{
-HTTP/1.1 200 OK
-Vary: Accept
-Server: MochiWeb/1.1 WebMachine/0.97
-Expires: Fri, 01 Jan 2021 00:00:00 GMT
-ETag: /demo/authdemo
-Date: Sun, 15 Mar 2009 02:59:02 GMT
-Content-Type: text/html
-Content-Length: 59
-
-<html><body>Hello authdemo from webmachine.
-</body></html>
-}}}
-
-For more details, read the source of the resources linked at the top of this page. 
-
+The simplest possible example is the one produced via the [[QuickStart]].
+
+For an example of a read/write filesystem server showing several interesting features and supporting GET, PUT, DELETE, and POST, see [[FixThisLink|demo_fs_resource].
+
+For a very simple resource demonstrating content negotiation, basic auth, and some caching headers, see [[FixThisLink|webmachine_demo_resource]].
+
+Some example code based on webmachine_demo_resource follows.
+
+The simplest working resource could export only one function in addition to init/1:
+
+{{{
+#!erlang
+-module(webmachine_demo_resource).
+-export([init/1, to_html/2]).
+-include_lib("webmachine/include/webmachine.hrl").
+
+init([]) -> {ok, undefined}.
+
+to_html(ReqData, Context) -> {"<html><body>Hello, new world</body></html>", ReqData, Context}.
+}}}
+
+That's really it -- a working webmachine resource. That resource will respond to all valid GET requests with the exact same response.
+
+Many interesting bits of HTTP are handled automatically by Webmachine. For instance, if a client sends a request to that trivial resource with an Accept header that does not allow for a text/html response, they will receive a 406 Not Acceptable.
+
+Suppose I wanted to serve a plaintext client as well. I could note that I provide more than just HTML:
+
+{{{
+#!erlang
+content_types_provided(ReqData, Context) ->
+   {[{"text/html", to_html},{"text/plain",to_text}], ReqData, Context}.
+}}}
+
+I already have my HTML representation produced, so I add a text one:
+(and while I'm at it, I'll show that it's trivial to produce dynamic content as well)
+
+{{{
+#!erlang
+to_text(ReqData, Context) ->
+    Path = wrq:disp_path(ReqData),
+    Body = io_lib:format("Hello ~s from webmachine.~n", [Path]),
+    {Body, ReqData, Context}.
+}}}
+
+Now that this resource provides multiple media types, it automatically performs conneg:
+
+{{{
+$ telnet localhost 8000
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+GET /demo/a/resource/path HTTP/1.1
+Accept: text/plain
+
+HTTP/1.1 200 OK
+Vary: Accept
+Server: MochiWeb/1.1 WebMachine/0.97
+Date: Sun, 15 Mar 2009 02:54:02 GMT
+Content-Type: text/plain
+Content-Length: 39
+
+Hello a/resource/path from webmachine.
+}}}
+
+What about authorization? Webmachine resources default to assuming the client is authorized, but that can easily be overridden. Here's an overly simplistic but illustrative example:
+
+{{{
+#!erlang
+is_authorized(ReqData, Context) ->
+    case wrq:disp_path(ReqData) of
+        "authdemo" -> 
+            case wrq:get_req_header("authorization", ReqData) of
+                "Basic "++Base64 ->
+                    Str = base64:mime_decode_to_string(Base64),
+                    case string:tokens(Str, ":") of
+                        ["authdemo", "demo1"] ->
+                            {true, ReqData, Context};
+                        _ ->
+                            {"Basic realm=webmachine", ReqData, Context}
+                    end;
+                _ ->
+                    {"Basic realm=webmachine", ReqData, Context}
+            end;
+        _ -> {true, ReqData, Context}
+    end.
+}}}
+
+With that function in the resource, all paths except {{{ /authdemo }}} from this resource's root are authorized. For that one path, the UA will be asked to do basic authorization with the user/pass of authdemo/demo1. It should go without saying that this isn't quite the same function that we use in our real apps, but it is nice and simple.
+
+To see that it works, you can point your browser at {{{ http://localhost:8000/demo/authdemo }}} with the demo app running:
+
+{{{
+$ curl -v http://localhost:8000/demo/authdemo
+> GET /demo/authdemo HTTP/1.1
+> Host: localhost:8000
+> Accept: */*
+> 
+< HTTP/1.1 401 Unauthorized
+< WWW-Authenticate: Basic realm=webmachine
+< Server: MochiWeb/1.1 WebMachine/0.97
+< Date: Sun, 15 Mar 2009 02:57:43 GMT
+< Content-Length: 0
+< 
+}}}
+{{{
+$ curl -v -u authdemo:demo1 http://localhost:8000/demo/authdemo 
+* Server auth using Basic with user 'authdemo'
+> GET /demo/authdemo HTTP/1.1
+> Authorization: Basic YXV0aGRlbW86ZGVtbzE=
+> Host: localhost:8000
+> Accept: */*
+> 
+< HTTP/1.1 200 OK
+< Vary: Accept
+< Server: MochiWeb/1.1 WebMachine/0.97
+< Date: Sun, 15 Mar 2009 02:59:02 GMT
+< Content-Type: text/html
+< Content-Length: 59
+< 
+<html><body>Hello authdemo from webmachine.
+</body></html>
+}}}
+
+HTTP caching support is also quite easy, with functions allowing resources to define (e.g.) {{{ last_modified }}} , {{{ expires }}}, and {{{ generate_etag.}}} For instance, since representations of this resource vary only by URI Path, I could use an extremely simple entity tag unfit for most real applications but sufficient for this example:
+
+{{{
+#!erlang
+generate_etag(ReqData, Context) -> {wrq:raw_path(ReqData), ReqData, Context}.
+}}}
+
+Similarly, here's a trivial expires rule:
+
+{{{
+#!erlang
+expires(ReqData, Context) -> {{{2021,1,1},{0,0,0}}, ReqData, Context}.
+}}}
+
+And now the response from our earlier request is appropriately tagged:
+
+{{{
+HTTP/1.1 200 OK
+Vary: Accept
+Server: MochiWeb/1.1 WebMachine/0.97
+Expires: Fri, 01 Jan 2021 00:00:00 GMT
+ETag: /demo/authdemo
+Date: Sun, 15 Mar 2009 02:59:02 GMT
+Content-Type: text/html
+Content-Length: 59
+
+<html><body>Hello authdemo from webmachine.
+</body></html>
+}}}
+
+For more details, read the source of the resources linked at the top of this page. 
+
+
 
 We believe that by giving Web developers a framework with conventions that directly map to HTTP and REST, we help them to write and extend Web applications quickly while not dictating the shape of the rest of their application.  The resulting applications are straightforward to examine and maintain, and have very easily understood HTTP semantics.
 
-{{http://www.iago.org/bcn/wmwiki/Home.gif}}
+
+
+
-== Getting going right away. ==
-
-Make sure that you have a working Erlang/OTP release, R12B3 or later.
-
-Get the webmachine code:
-
-{{{
-#!bash
-hg clone http://bitbucket.org/justin/webmachine/ webmachine-read-only
-}}}
-
-Build webmachine:
-
-{{{
-#!bash
-cd webmachine-read-only
-make
-}}}
-
-Create, build, and start the skeleton resource:
-
-{{{
-#!bash
-./scripts/new_webmachine.erl mywebdemo /tmp
-cd /tmp/mywebdemo
-make
-./start.sh
-}}}
-
-Take a look! Point a web browser at http://localhost:8000/
-
-To make this resource handle URI paths other than /, modify the [[DispatchConfiguration]] term in /tmp/mywebdemo/src/mywebdemo_sup.erl; to make that resource to more interesting things, modify the [[WebmachineResources|resource]] itself at /tmp/mywebdemo/src/mywebdemo_resource.erl.
-
-To learn how to do more interesting things, read the [[Home|rest of this wiki]]. 
+== Getting going right away. ==
+
+Make sure that you have a working Erlang/OTP release, R12B3 or later.
+
+Get the webmachine code:
+
+{{{
+#!bash
+hg clone http://bitbucket.org/justin/webmachine/ webmachine-read-only
+}}}
+
+Build webmachine:
+
+{{{
+#!bash
+cd webmachine-read-only
+make
+}}}
+
+Create, build, and start the skeleton resource:
+
+{{{
+#!bash
+./scripts/new_webmachine.erl mywebdemo /tmp
+cd /tmp/mywebdemo
+make
+./start.sh
+}}}
+
+Take a look! Point a web browser at http://localhost:8000/
+
+To make this resource handle URI paths other than /, modify the [[DispatchConfiguration]] term in /tmp/mywebdemo/src/mywebdemo_sup.erl; to make that resource to more interesting things, modify the [[WebmachineResources|resource]] itself at /tmp/mywebdemo/src/mywebdemo_resource.erl.
+
+To learn how to do more interesting things, read the [[Home|rest of this wiki]]. 
+

WebmachineDebugging.wiki

-Having trouble with your webmachine resource?  Try debugging it with the webmachine trace utility!
-
-== Basic Use ==
-
-To get started, first change your resource's {{{ init/1 }}} function to return {{{ {trace, Path} }}} instead of {{{ ok }}}.  For example:
-
-{{{
-#!erlang
-init(Config) ->
-   {{trace, "/tmp"}, Config}.  %% debugging code
-   %%{ok, Config}.             %% regular code
-}}}
-
-Rebuild and reload the module, then in your webmachine application's shell, type:
-{{{
-#!erlang
-wmtrace_resource:add_dispatch_rule("wmtrace", "/tmp").
-}}}
-
-Now issue the HTTP request that you're trying to debug.  Once it has finished, point your browser at {{{ http://YOUR_HOST/wmtrace/ }}}.  You'll see one or more trace files available for inspection.  Click on one of them to navigate to the trace inspection utility, which will look something like this:
-
-{{basic-trace-labeled.png|Basic Trace}}
-
-The example above is a trace of a resource that responded to a GET of the root path (as you can see in the //Detail Panel//), and ran all the way to a 200 response code (as you can see in the //Decision Graph//).
-
-The graph starts small, so you can get a quick view of the path your resource took through it.  You can zoom in and out of the //Decision Graph// by using the //Zoom Controls//.
-
-The path your resource took through the graph is highlighted with a dark grey line.  Hovering your mouse over the outlined decision points along that line will pop up a tool tip with the name of the decision, and the names of the functions in your resource that were called at that point.  Clicking on a decision will flip the //Detail Panel// to the //Decision Tab//, where information about that decision will be displayed.
-
-If your resource traversed the graph all the way to one of the standard, non-error return codes, the box for that return code will be outlined.  If your resource instead returned a non-standard or error code, a red circle will be drawn next to the last decision point your resource reached.  Clicking on either of these types of endpoints will flip the //Detail Panel// to the //Response Tab//, where information about the response will be displayed.
-
-The //Detail Panel// has three tabs: Request (labeled //Q//), Response (labeled //R//), and Decision (labeled //D//).  Clicking each of these will show information about the request, response, or current decision, respectively.
-
-{{basic-trace-request-tab.png|Detail Panel Request Tab}}
-
-The //Request Tab// shows details about what the client requested.  The method and path are displayed at the top, headers below that, and body (if available) at the bottom.
-
-{{basic-trace-response-tab.png|Detail Panel Response Tab}}
-
-The //Response Tab// shows details about how your resource responded.  The response code is displayed at the top, headers below that, and body (if available) at the bottom.
-
-{{basic-trace-decision-tab.png|Detail Panel Decision Tab}}
-
-The //Decision Tab// shows details about the currently selected decision.  The decision's name is displayed in a dropdown at the top (changing this dropdown or clicking on a decision in the graph will change which decision is displayed).  The list of the functions called in the resource's module is displayed in a dropdown below the decision.  The arguments with which the function was called are displayed just below the function's name, and the return value of the function is displayed at the bottom of the panel.
-
-The //Detail Panel// can be resized by clicking and dragging the tabs or the dark grey border to the left or right.  Clicking the border will toggle the panel's visibility.
-
-== Configuration Details ==
-
-The Webmachine trace tool is divided into two parts: one produces the trace logs, while the other produces the visualization.
-
-=== Trace Log Production Configuration ===
-
-You may configure the path under which trace files are stored by specifying that path as the {{{ Path }}} part of your resource module's {{{ init/1 }}} return value.  Every time a request is made to that resource, a new trace file will be created in the specified directory.
-
-**//Warning//**: Trace files can be large.  It is advised that you do not leave tracing enabled on a large-content-producing or high-hit-rate resource.
-
-The path may be either absolute:
-
-{{{
-#!erlang
-init(Config) ->
-   {{trace, "/tmp/traces"}, Config}. %% absolute path /tmp/traces
-}}}
-
-or relative to your application's root:
-
-{{{
-#!erlang
-init(Config) ->
-   {{trace, "traces"}, Config}. %% "traces" directory in application's root
-}}}
-
-=== Trace Viewer Configuration ===
-
-The viewer is configured by its entry in the [[DispatchConfiguration|dispatch list]].  Two functions make modifying that entry easy: {{{ wmtrace_resource:add_dispatch_rule/2 }}} and {{{ wmtrace_resource:remove_dispatch_rules/0 }}}.
-
-Call {{{ add_dispatch_rule/2 }}} with the HTTP-exported path, and the path to the trace files.  For example, to expose the viewer at {{{ http://YOUR_HOST/dev/wmtrace/ }}} and point it at the trace files in {{{ /tmp/traces }}}, type in your application's erlang shell:
-
-{{{
-#!erlang
-wmtrace_resource:add_dispatch_rule("dev/wmtrace", "/tmp/traces").
-}}}
-
-If you know that you always want the viewer enabled and configured in a specific way, you can also add a line like the following to your application's dispatch list:
-
-{{{
-#!erlang
-{["dev", "wmtrace", '*'], wmtrace_resource, [{trace_dir, "/tmp/traces"}]}
-}}}
-
-To disable all trace viewer resources at any point, just execute {{{ wmtrace_resource:remove_dispatch_rules/0 }}} in your application's erlang shell.
-
-== Trace Log Format ==
-
-The trace file is fairly straightforward, if you want to read it with {{{ less }}}:
-
- * {{{ {decision, X}. }}} indicates that a decision point was reached
- * {{{ {attempt, Module, Function, Args}. }}} indicates that a call to {{{ Module:Function(Args) }}} was made.
- * {{{ {result, Module, Function, Result}. }}} indicates that the call to {{{ Module:Function(Args) }}} returned {{{ Result }}}.
- * {{{ {not_expored, Module, Function, Args}. }}} indicates that {{{ Module:Function(Args) }}} would have been called, but it was not exported (or not defined) by the module
-
-The format should be such that a {{{ file:consult/1 }}} will give you a list of the lines as erlang terms.
-
-== Troubleshooting the Trace Utility ==
-
-The trace utility currently has trouble if any of your resources return a {{{ fun }}}, because of the way they serialize in the log file.  If you see errors in your webmachine log like:
-
-{{{
-{error,{badmatch,{error,{597,erl_parse,["syntax error before: ",["Fun"]]}}},
-       [{wmtrace_resource,produce_html,2},
-}}}
-
-when trying to get to the trace utility, you need to clean up those funs in your log file.  A simple way to do it is to run this command at a prompt in your traces directory:
-
-{{{
-for x in *.wmtrace; do sed "s/#Fun<.*>/wmtrace_anonymous_function_todo/" $x > $x-fixed; done
-}}}
-
-Anywhere you would have seen a {{{ fun }}}, you'll now see {{{ wmtrace_anonymous_function_todo }}}.
+Having trouble with your webmachine resource?  Try debugging it with the webmachine trace utility!
+
+== Basic Use ==
+
+To get started, first change your resource's {{{ init/1 }}} function to return {{{ {trace, Path} }}} instead of {{{ ok }}}.  For example:
+
+{{{
+#!erlang
+init(Config) ->
+   {{trace, "/tmp"}, Config}.  %% debugging code
+   %%{ok, Config}.             %% regular code
+}}}
+
+Rebuild and reload the module, then in your webmachine application's shell, type:
+{{{
+#!erlang
+wmtrace_resource:add_dispatch_rule("wmtrace", "/tmp").
+}}}
+
+Now issue the HTTP request that you're trying to debug.  Once it has finished, point your browser at {{{ http://YOUR_HOST/wmtrace/ }}}.  You'll see one or more trace files available for inspection.  Click on one of them to navigate to the trace inspection utility, which will look something like this:
+
+{{basic-trace-labeled.png|Basic Trace}}
+
+The example above is a trace of a resource that responded to a GET of the root path (as you can see in the //Detail Panel//), and ran all the way to a 200 response code (as you can see in the //Decision Graph//).
+
+The graph starts small, so you can get a quick view of the path your resource took through it.  You can zoom in and out of the //Decision Graph// by using the //Zoom Controls//.
+
+The path your resource took through the graph is highlighted with a dark grey line.  Hovering your mouse over the outlined decision points along that line will pop up a tool tip with the name of the decision, and the names of the functions in your resource that were called at that point.  Clicking on a decision will flip the //Detail Panel// to the //Decision Tab//, where information about that decision will be displayed.
+
+If your resource traversed the graph all the way to one of the standard, non-error return codes, the box for that return code will be outlined.  If your resource instead returned a non-standard or error code, a red circle will be drawn next to the last decision point your resource reached.  Clicking on either of these types of endpoints will flip the //Detail Panel// to the //Response Tab//, where information about the response will be displayed.
+
+The //Detail Panel// has three tabs: Request (labeled //Q//), Response (labeled //R//), and Decision (labeled //D//).  Clicking each of these will show information about the request, response, or current decision, respectively.
+
+{{basic-trace-request-tab.png|Detail Panel Request Tab}}
+
+The //Request Tab// shows details about what the client requested.  The method and path are displayed at the top, headers below that, and body (if available) at the bottom.
+
+{{basic-trace-response-tab.png|Detail Panel Response Tab}}
+
+The //Response Tab// shows details about how your resource responded.  The response code is displayed at the top, headers below that, and body (if available) at the bottom.
+
+{{basic-trace-decision-tab.png|Detail Panel Decision Tab}}
+
+The //Decision Tab// shows details about the currently selected decision.  The decision's name is displayed in a dropdown at the top (changing this dropdown or clicking on a decision in the graph will change which decision is displayed).  The list of the functions called in the resource's module is displayed in a dropdown below the decision.  The arguments with which the function was called are displayed just below the function's name, and the return value of the function is displayed at the bottom of the panel.
+
+The //Detail Panel// can be resized by clicking and dragging the tabs or the dark grey border to the left or right.  Clicking the border will toggle the panel's visibility.
+
+== Configuration Details ==
+
+The Webmachine trace tool is divided into two parts: one produces the trace logs, while the other produces the visualization.
+
+=== Trace Log Production Configuration ===
+
+You may configure the path under which trace files are stored by specifying that path as the {{{ Path }}} part of your resource module's {{{ init/1 }}} return value.  Every time a request is made to that resource, a new trace file will be created in the specified directory.
+
+**//Warning//**: Trace files can be large.  It is advised that you do not leave tracing enabled on a large-content-producing or high-hit-rate resource.
+
+The path may be either absolute:
+
+{{{
+#!erlang
+init(Config) ->
+   {{trace, "/tmp/traces"}, Config}. %% absolute path /tmp/traces
+}}}
+
+or relative to your application's root:
+
+{{{
+#!erlang
+init(Config) ->
+   {{trace, "traces"}, Config}. %% "traces" directory in application's root
+}}}
+
+=== Trace Viewer Configuration ===
+
+The viewer is configured by its entry in the [[DispatchConfiguration|dispatch list]].  Two functions make modifying that entry easy: {{{ wmtrace_resource:add_dispatch_rule/2 }}} and {{{ wmtrace_resource:remove_dispatch_rules/0 }}}.
+
+Call {{{ add_dispatch_rule/2 }}} with the HTTP-exported path, and the path to the trace files.  For example, to expose the viewer at {{{ http://YOUR_HOST/dev/wmtrace/ }}} and point it at the trace files in {{{ /tmp/traces }}}, type in your application's erlang shell:
+
+{{{
+#!erlang
+wmtrace_resource:add_dispatch_rule("dev/wmtrace", "/tmp/traces").
+}}}
+
+If you know that you always want the viewer enabled and configured in a specific way, you can also add a line like the following to your application's dispatch list:
+
+{{{
+#!erlang
+{["dev", "wmtrace", '*'], wmtrace_resource, [{trace_dir, "/tmp/traces"}]}
+}}}
+
+To disable all trace viewer resources at any point, just execute {{{ wmtrace_resource:remove_dispatch_rules/0 }}} in your application's erlang shell.
+
+== Trace Log Format ==
+
+The trace file is fairly straightforward, if you want to read it with {{{ less }}}:
+
+ * {{{ {decision, X}. }}} indicates that a decision point was reached
+ * {{{ {attempt, Module, Function, Args}. }}} indicates that a call to {{{ Module:Function(Args) }}} was made.
+ * {{{ {result, Module, Function, Result}. }}} indicates that the call to {{{ Module:Function(Args) }}} returned {{{ Result }}}.
+ * {{{ {not_expored, Module, Function, Args}. }}} indicates that {{{ Module:Function(Args) }}} would have been called, but it was not exported (or not defined) by the module
+
+The format should be such that a {{{ file:consult/1 }}} will give you a list of the lines as erlang terms.
+
+== Troubleshooting the Trace Utility ==
+
+The trace utility currently has trouble if any of your resources return a {{{ fun }}}, because of the way they serialize in the log file.  If you see errors in your webmachine log like:
+
+{{{
+{error,{badmatch,{error,{597,erl_parse,["syntax error before: ",["Fun"]]}}},
+       [{wmtrace_resource,produce_html,2},
+}}}
+
+when trying to get to the trace utility, you need to clean up those funs in your log file.  A simple way to do it is to run this command at a prompt in your traces directory:
+
+{{{
+for x in *.wmtrace; do sed "s/#Fun<.*>/wmtrace_anonymous_function_todo/" $x > $x-fixed; done
+}}}
+
+Anywhere you would have seen a {{{ fun }}}, you'll now see {{{ wmtrace_anonymous_function_todo }}}.
+

WebmachineMechanics.wiki

-== How does this Webmachine thing work, anyway? ==
-
-This page documents the basic mechanics of Webmachine from the point of view of a single incoming HTTP Request, documenting the behavior of Webmachine through to the HTTP Response.
-
-(This is a bit different from what you might get with a "Web Framework" as we're not going to talk about MVC, ORMs, or anything else about the rest of the shape of your application.  We believe that you know better than we do how to structure your own app -- Webmachine's job is to make sure that your app's presence on the Web is well-behaved and well-structured.)
-
-When a request is initially received by Webmachine it is handled by the [[DispatchConfiguration|dispatcher]].  If the dispatcher does not find a matching resource then it will immediately respond with a 404 Not Found.  If a match is found then a [[WebmachineReqData|request data record]] is created and the matching [[WebmachineResources|resource]] is kicked off via its {{{ init/1 }}} function.
-
-The resource then flows through the decision core, which is effectively just running the request through the [[BigHTTPGraph|HTTP flowchart]].  At each decision point (diamond) in the diagram, Webmachine will determine which path to follow.  In some cases it can determine the path purely from the request data -- for instance, the path from decision {{{ C3 }}} depends purely on whether the client sent an {{{ Accept }}} header.  In many cases, however, the decision is application-specific -- the path from {{{ B10 }}} depends on the value the [[WebmachineResources|resource]] returns from {{{ allowed_methods.}}}  Eventually the chosen path will terminate at one of the rectangles on the diagram.  At that point Webmachine will send an appropriate HTTP response, with the headers and body dependent on the path through the diagram and the values returned by the resource's functions.
-
-Most of the time you don't need to worry about this big diagram, though -- just define the [[WebmachineResources|resource functions]] relevant to your app and Webmachine will do the rest.  A good understanding of this central mechanism in Webmachine is most useful when [[WebmachineDebugging|debugging your resources]].
-
-From the way that webmachine's decision core works, it follows that Webmachine's HTTP behavior is transactional.  Each HTTP Request is fully received, and the resulting HTTP Response is then fully constructed before being returned.  This means that while Webmachine is suitable for a great many Web applications it is not a good fit for an application that will gradually or continuously stream responses back to clients inside the context of a single HTTP Request.
-
-A useful way to build Webmachine applications is often just to write a single function such as {{{ to_html }}} to provide the most basic of stubs; when that function exists (or any other returned by {{{content_types_provided}}}) you can produce {{{200 OK}}} responses.  After that, you can easily extend your application's Web behavior simply by filling in the other [[WebmachineResources|resource functions]] as desired.
+== How does this Webmachine thing work, anyway? ==
+
+This page documents the basic mechanics of Webmachine from the point of view of a single incoming HTTP Request, documenting the behavior of Webmachine through to the HTTP Response.
+
+(This is a bit different from what you might get with a "Web Framework" as we're not going to talk about MVC, ORMs, or anything else about the rest of the shape of your application.  We believe that you know better than we do how to structure your own app -- Webmachine's job is to make sure that your app's presence on the Web is well-behaved and well-structured.)
+
+When a request is initially received by Webmachine it is handled by the [[DispatchConfiguration|dispatcher]].  If the dispatcher does not find a matching resource then it will immediately respond with a 404 Not Found.  If a match is found then a [[WebmachineReqData|request data record]] is created and the matching [[WebmachineResources|resource]] is kicked off via its {{{ init/1 }}} function.
+
+The resource then flows through the decision core, which is effectively just running the request through the [[BigHTTPGraph|HTTP flowchart]].  At each decision point (diamond) in the diagram, Webmachine will determine which path to follow.  In some cases it can determine the path purely from the request data -- for instance, the path from decision {{{ C3 }}} depends purely on whether the client sent an {{{ Accept }}} header.  In many cases, however, the decision is application-specific -- the path from {{{ B10 }}} depends on the value the [[WebmachineResources|resource]] returns from {{{ allowed_methods.}}}  Eventually the chosen path will terminate at one of the rectangles on the diagram.  At that point Webmachine will send an appropriate HTTP response, with the headers and body dependent on the path through the diagram and the values returned by the resource's functions.
+
+Most of the time you don't need to worry about this big diagram, though -- just define the [[WebmachineResources|resource functions]] relevant to your app and Webmachine will do the rest.  A good understanding of this central mechanism in Webmachine is most useful when [[WebmachineDebugging|debugging your resources]].
+
+From the way that webmachine's decision core works, it follows that Webmachine's HTTP behavior is transactional.  Each HTTP Request is fully received, and the resulting HTTP Response is then fully constructed before being returned.  This means that while Webmachine is suitable for a great many Web applications it is not a good fit for an application that will gradually or continuously stream responses back to clients inside the context of a single HTTP Request.
+
+A useful way to build Webmachine applications is often just to write a single function such as {{{ to_html }}} to provide the most basic of stubs; when that function exists (or any other returned by {{{content_types_provided}}}) you can produce {{{200 OK}}} responses.  After that, you can easily extend your application's Web behavior simply by filling in the other [[WebmachineResources|resource functions]] as desired.
+