Commits

Anonymous committed 2bf8c96

initial files for webmachine.basho.com site

  • Participants
  • Parent commits 537c6a0

Comments (0)

Files changed (35)

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine blogging" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>other writing about Webmachine</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>What else can I read?</h3>
+
+<p>
+In addition to the documentation on this site and the source code on bitbucket, some useful Webmachine writing can be found on blogs and elsewhere.  A small sampling of these is here:
+</p>
+<p>
+The <a href="http://blog.therestfulway.com/">restful way</a> blog is almost entirely dedicated to Webmachine.
+</p>
+<p>
+The <a href="http://blog.beerriot.com/">BeerRiot blog</a> contains multiple topics, including a wealth of examples and discussion of Webmachine.
+</p>
+<p>
+The blog of <a href="http://blog.argv0.net/">Andy Gross</a> has some
+useful hints and tutorials.
+</p>
+<p>
+Paul Mineiro posted about
+<a href="http://dukesoferl.blogspot.com/2009/08/dynamically-loading-webmachine.html">dynamically loading webmachine resources</a>.
+</p>
+<p>
+<a href="http://weblog.hypotheticalabs.com/?page_id=413">Kevin Smith</a>
+teaches an excellent Erlang training class which often culminates with
+development of applications in Webmachine.
+</p>
+<p>
+There is a fairly low traffic
+<a href="http://lists.therestfulway.com/mailman/listinfo/webmachine_lists.therestfulway.com">mailing list</a>
+for technical discussion of Webmachine.
+</p>
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine contact info" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine contact information</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine contact information</h3>
+
+<p>
+Have questions about Webmachine that aren't answered here? We'd love
+to hear from you.
+</p>
+<p>
+Subscribers to the <a href="http://lists.therestfulway.com/mailman/listinfo/webmachine_lists.therestfulway.com">Webmachine mailing list</a> include both users and the core development team.
+</p>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/css/style-1c.css

+/* global reset */
+*{ margin: 0; padding: 0; }*
+:focus, :active { outline: 0; }
+
+body { font: .9em Georgia, "Times New Roman", Sans-Serif; background: #fff url(../images/bg.gif) repeat-x; color: #333; }
+a { color: #3333FF; text-decoration: none; }
+img { border: 0; }
+h1 {  float: left; margin: 20px 0 50px; font-size: 4em; color: #fff; }
+h2 { font-size: 2.4em; font-weight: normal; margin: 0 0 20px; }
+h2 a:hover { background: #3333FF; color: #fff; }
+.hr { color: #ccc; }
+p  { margin: 5px 0 15px; line-height: 1.6em; }
+#content { margin: 0 auto; width: 900px; }
+#top { float: right; margin: 38px 0 30px 0;}
+	#top li { list-style: none; display: inline; }
+	#top li a { float: left; padding: 6px 20px; margin: 3px 2px 0 0; color: #3333FF; }
+	#top li a.current { color: #fff; background: #3333FF; }
+	#top li a:hover { background: #808080; color: #fff; }
+#intro { clear: both; padding: 15px 0 1px 20px; border: 1px solid #dedede; font-size: 1.3em; background: #eee; margin: 0 0 30px; }
+#left { float: left; width: 830px; margin: 0 0 15px; }
+#right { float: right; width: 0px; }
+#right h3 { border-bottom: 1px solid #ccc; margin: 0 0 10px; }
+#right img { margin: 0 3px 3px 0; border: 2px solid #eee; padding: 2px; }
+#right li { list-style: none; }
+	#right li a { display: block; border-bottom: 1px solid #ccc; padding: 5px 5px; }
+#footer { clear: both; padding: 15px 0; border-top: 1px solid #ccc; }
+	#r { float: right; }
+dt { font-weight:bold; }
+dd { margin: 0.5em 0 0.5em 1em; }	
+
+/* table */
+
+.fwf {
+    font: 12px "Courier";
+    color: #111;
+}
+
+.lhcol {
+    width: 200px;
+}
+
+.x_check {
+    padding-left:3px;
+    font: 12px "Courier";
+}
+
+table {
+	width: 100%;
+	padding: 0;
+	border-spacing: 0px;
+	border-collapse: collapse;
+	margin: 5px;
+	margin-bottom: 15px;
+}
+
+th {
+	font: bold 12px "Georgia", Verdana, Arial, Helvetica, sans-serif;
+	/* color: #4f6b72; */
+	border: 1px solid #999;
+	letter-spacing: 2px;
+	text-transform: uppercase;
+	text-align: left;
+	padding: 6px 6px 6px 12px;
+	background: #ddd;
+}
+
+th.nobg {
+	border-top: 0;
+	border-left: 0;
+	border-right: 1px solid #999;
+	background: none;
+}
+
+td {
+	border: 1px solid #999;
+	background: #fff;
+	padding: 6px 6px 6px 12px;
+    vertical-align: top;
+    font: inherit;
+    color: #222;
+}
+
+
+td.alt {
+	background: #F5FAFA;
+	color: #797268;
+}
+
+th.spec {
+	border-left: 1px solid #999;
+	border-top: 0;
+	background: #fff url(images/bullet1.gif) no-repeat;
+	font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
+}
+
+th.specalt {
+	border-left: 1px solid #999;
+	border-top: 0;
+	background: #f5fafa url(images/bullet2.gif) no-repeat;
+	font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
+	color: #797268;
+}
+

www/css/style.css

+/* global reset */
+*{ margin: 0; padding: 0; }*
+:focus, :active { outline: 0; }
+
+body { font: .9em Georgia, "Times New Roman", Sans-Serif; background: #fff url(../images/bg.gif) repeat-x; color: #333; }
+a { color: #3333FF; text-decoration: none; }
+img { border: 0; }
+h1 {  float: left; margin: 20px 0 50px; font-size: 4em; color: #fff; }
+h2 { font-size: 2.4em; font-weight: normal; margin: 0 0 20px; }
+h2 a:hover { background: #3333FF; color: #fff; }
+.hr { color: #ccc; }
+p  { margin: 5px 0 15px; line-height: 1.6em; }
+#content { margin: 0 auto; width: 900px; }
+#top { float: right; margin: 38px 0 30px 0;}
+	#top li { list-style: none; display: inline; }
+	#top li a { float: left; padding: 6px 20px; margin: 3px 2px 0 0; color: #3333FF; }
+	#top li a.current { color: #fff; background: #3333FF; }
+	#top li a:hover { background: #808080; color: #fff; }
+#intro { clear: both; padding: 15px 0 1px 20px; border: 1px solid #dedede; font-size: 1.3em; background: #eee; margin: 0 0 30px; }
+#left { float: left; width: 550px; margin: 0 0 15px; }
+#right { float: right; width: 280px; }
+#right h3 { border-bottom: 1px solid #ccc; margin: 0 0 10px; }
+#right img { margin: 0 3px 3px 0; border: 0 solid #eee; padding: 2px; }
+#right li { list-style: none; }
+	#right li a { display: block; border-bottom: 1px solid #ccc; padding: 5px 5px; }
+#footer { clear: both; padding: 15px 0; border-top: 1px solid #ccc; }
+	#r { float: right; }
+dt { font-weight:bold; }
+dd { margin: 0.5em 0 0.5em 1em; }	
+
+/* table */
+
+.fwf {
+    font: 12px "Courier";
+    color: #111;
+}
+
+.lhcol {
+    width: 200px;
+}
+
+.x_check {
+    padding-left:3px;
+    font: 12px "Courier";
+}
+
+table {
+	width: 100%;
+	padding: 0;
+	border-spacing: 0px;
+	border-collapse: collapse;
+	margin: 5px;
+	margin-bottom: 15px;
+}
+
+th {
+	font: bold 12px "Georgia", Verdana, Arial, Helvetica, sans-serif;
+	/* color: #4f6b72; */
+	border: 1px solid #999;
+	letter-spacing: 2px;
+	text-transform: uppercase;
+	text-align: left;
+	padding: 6px 6px 6px 12px;
+	background: #ddd;
+}
+
+th.nobg {
+	border-top: 0;
+	border-left: 0;
+	border-right: 1px solid #999;
+	background: none;
+}
+
+td {
+	border: 1px solid #999;
+	background: #fff;
+	padding: 6px 6px 6px 12px;
+    vertical-align: top;
+    font: inherit;
+    color: #222;
+}
+
+
+td.alt {
+	background: #F5FAFA;
+	color: #797268;
+}
+
+th.spec {
+	border-left: 1px solid #999;
+	border-top: 0;
+	background: #fff url(images/bullet1.gif) no-repeat;
+	font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
+}
+
+th.specalt {
+	border-left: 1px solid #999;
+	border-top: 0;
+	background: #f5fafa url(images/bullet2.gif) no-repeat;
+	font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
+	color: #797268;
+}
+

www/debugging.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine debugging" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine debugging</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine debugging</h3>
+
+<p>
+Having trouble with your webmachine resource?  Try debugging it with
+the webmachine trace utility!
+</p>
+
+<h2>Basic Use</h2>
+
+<p>
+To get started, first change your resource's <code>init/1</code>
+function to return <code>{trace, Path}</code> instead of
+<code>ok</code>.  For example:
+</p>
+
+<pre>
+init(Config) ->
+   {{trace, "/tmp"}, Config}.  %% debugging code
+   %%{ok, Config}.             %% regular code
+</pre>
+
+<p>
+Rebuild and reload the module, then in your webmachine application's
+shell, type:
+</p>
+
+<pre>
+wmtrace_resource:add_dispatch_rule("wmtrace", "/tmp").
+</pre>
+
+<p>
+Now issue the HTTP request that you're trying to debug.  Once it has
+finished, point your browser at <code>http://YOUR_HOST/wmtrace/</code>.
+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:
+</p>
+
+<p><img src="images/basic-trace-labeled.png" alt="Basic Trace" title="Basic Trace" /></p>
+
+<p>
+The example above is a trace of a resource that responded to a GET of
+the root path (as you can see in the <em>Detail Panel</em>), and ran
+all the way to a 200 response code (as you can see in the <em>Decision
+Graph</em>).
+</p>
+
+<p>
+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 <em>Decision
+Graph</em> by using the <em>Zoom Controls</em>.
+</p>
+
+<p>
+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 <em>Detail
+Panel</em> to the <em>Decision Tab</em>, where information about that
+decision will be displayed.
+</p>
+<p>
+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 <em>Detail Panel</em> to the <em>Response Tab</em>, where
+information about the response will be displayed.
+</p>
+<p>
+The <em>Detail Panel</em> has three tabs: Request (labeled
+<em>Q</em>), Response (labeled <em>R</em>), and Decision (labeled
+<em>D</em>).  Clicking each of these will show information about the
+request, response, or current decision, respectively.
+</p>
+
+<p><img src="images/basic-trace-request-tab.png" alt="Detail Panel Request Tab" title="Detail Panel Request Tab" /></p>
+
+<p>
+The <em>Request Tab</em> 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.
+</p>
+
+<p><img src="images/basic-trace-response-tab.png" alt="Detail Panel Response Tab" title="Detail Panel Response Tab" /></p>
+
+<p>
+The <em>Response Tab</em> 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.
+</p>
+
+<p><img src="images/basic-trace-decision-tab.png" alt="Detail Panel Decision Tab" title="Detail Panel Decision Tab" /></p>
+
+<p>
+The <em>Decision Tab</em> 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.
+</p>
+<p>
+The <em>Detail Panel</em> 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.
+</p>
+
+<h2>Configuration Details</h2>
+
+<p>
+The Webmachine trace tool is divided into two parts: one produces the
+trace logs, while the other produces the visualization.
+</p>
+
+<h3>Trace Log Production Configuration</h3>
+
+<p>
+You may configure the path under which trace files are stored by
+specifying that path as the <code>Path</code> part of your resource
+module's <code>init/1</code> return value.  Every time a request is
+made to that resource, a new trace file will be created in the
+specified directory.
+</p>
+<p>
+<strong><em>Warning</em></strong>: 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.
+</p>
+<p>
+The path may be either absolute:
+</p>
+<pre>
+init(Config) ->
+   {{trace, "/tmp/traces"}, Config}. %% absolute path /tmp/traces
+</pre>
+
+<p>or relative to your application's root:</p>
+
+<p>
+<pre>
+init(Config) ->
+   {{trace, "traces"}, Config}. %% "traces" directory in application's root
+</pre>
+</p>
+
+<h3>Trace Viewer Configuration</h3>
+
+<p>
+The viewer is configured by its entry in the
+<a href="dispatcher.html">dispatch list</a>.
+Two functions make modifying that entry easy:
+<code>wmtrace_resource:add_dispatch_rule/2</code>
+and <code>wmtrace_resource:remove_dispatch_rules/0</code>.
+</p>
+<p>
+Call <code>add_dispatch_rule/2</code> with the HTTP-exported path, and
+the path to the trace files.  For example, to expose the viewer at
+<code>http://YOUR_HOST/dev/wmtrace/</code> and point it at the trace
+files in <code>/tmp/traces</code>, type in your application's erlang
+shell:
+</p>
+
+<pre>
+wmtrace_resource:add_dispatch_rule("dev/wmtrace", "/tmp/traces").
+</pre>
+
+<p>
+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:
+</p>
+
+<pre>
+{["dev", "wmtrace", '*'], wmtrace_resource, [{trace_dir, "/tmp/traces"}]}
+</pre>
+
+<p>
+To disable all trace viewer resources at any point, just execute
+<code>wmtrace_resource:remove_dispatch_rules/0</code> in your
+application's erlang shell.
+</p>
+
+<h2>Trace Log Format</h2>
+
+<p>
+The trace file is fairly straightforward, if you want to read it with
+<code>less</code>:
+</p>
+
+<ul><li><code> {decision, X}. </code> indicates that a decision point was reached
+
+</li><li><code> {attempt, Module, Function, Args}. </code> indicates that a call to <code> Module:Function(Args) </code> was made.
+</li><li><code> {result, Module, Function, Result}. </code> indicates that the call to <code> Module:Function(Args) </code> returned <code> Result </code>.
+
+</li><li><code> {not_expored, Module, Function, Args}. </code> indicates that <code> Module:Function(Args) </code> would have been called, but it was not exported (or not defined) by the module
+</li></ul>
+
+<p>
+The format should be such that a <code>file:consult/1</code> will
+give you a list of the lines as erlang terms.
+</p>
+
+<h2>Special Handling for Funs and Pids</h2>
+
+<p>
+Funs and Pids don't roundtrip through file serialization very well
+(<code>file:consult/1</code> will blow up on a fun or pid written to a
+file with <code>io:format("~p", [FunOrPid])</code>).  To deal with
+this, the trace logger prints a recognizable tuple translation instead
+of the fun or pid.
+</p>
+
+<h3>Fun Translation</h3>
+
+<p>
+Funs you might see in Erlang source as <code>fun io:format/2</code>
+will appear in a trace log as:
+</p>
+
+<pre>
+{'WMTRACE_ESCAPED_FUN',[{module,io},
+                        {name,format},
+                        {arity,2},
+                        {type,external}]}
+</pre>
+
+<p>
+Those that would be in Erlang source as <code> fun() -&gt; ok end
+</code> will appear in a trace log as:
+</p>
+
+<pre>
+{'WMTRACE_ESCAPED_FUN',[{module,sampletrace_resource},
+                        {name,'-to_html/2-fun-0-'},
+                        {arity,0},
+                        {type,local}]}
+</pre>
+
+<h3>Pid Translation</h3>
+
+<p>
+Pids are simply logged in a marked tuple, after being run through
+<code>erlang:pid_to_list/1</code>:
+</p>
+
+<pre>
+{'WMTRACE_ESCAPED_PID',"<0.74.0>"}
+</pre>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine decision flow" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine decision flow</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine decision flow</h3>
+
+<p>
+This diagram is illustrative of the flow of processing that a
+<a href="resources.html">webmachine resource</a> goes through
+from inception to response.
+</p>
+<p>
+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.
+</p>
+<p>
+A copy of v3 is found in the webmachine source tree for convenience.
+</p>
+<p>
+<img src="images/http-headers-status-v3.png" alt="http diagram v3" title="http diagram v3" />
+</p>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/dispatcher.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine request dispatching" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine request dispatching</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine request dispatching</h3>
+
+<p>
+This page describes the configuration of URI dispatch to resources
+in a webmachine application. The dispatch map data structure is a list
+of 3-tuples, where each entry is of the form {pathspec, resource,
+args}. The first pathspec in the list that matches the URI for a
+request will cause the corresponding resource to be used in handling
+that request.
+
+</p>
+<p>
+
+A <code>pathspec</code> is a list of pathterms. A pathterm is any of
+[string,atom,star] where star is just the atom of "*". The
+pathspec-matching is done by breaking up the request URI into tokens
+via the "/" separator and matching those tokens against the
+pathterms. A string pathterm will match a token if the token is equal
+to that string. A non-star atom will match any single token. The star
+atom (* in single quotes) will match any number of tokens, but may
+only be present as the last pathterm in a pathspec. If all tokens are
+matched and all pathterms are used, then the pathspec matches.  The
+tokens used are available in <code>wrq:path_tokens(ReqData)</code>
+in the resource functions.
+
+</p>
+<p>
+
+Any atom pathterms that were used in a match will cause a binding in
+the path_info element of the request's
+<a href="reqdata.html">ReqData</a>.  If
+there was a <code>foo</code> atom that matched the token
+<code>"bar"</code>, then <code>wrq:path_info(foo, ReqData)</code> will
+return <code>"bar"</code> inside the resource calls, and in any case
+<code>wrq:path_info(ReqData)</code> will return a Dict term with all
+the bindings, accessible via the <code>dict</code> standard library
+module.  If there was a star pathterm in the pathspec, then
+<code>wrq:disp_path(ReqData)</code> in a resource function will return
+the URI portion that was matched by the star.
+
+</p>
+<p>
+
+The <code> resource </code> is an atom identifying a
+<a href="resources.html">resource</a> that
+should handle a matching request. It will have the <code>args</code>
+(which must be a list) passed to its init function before request
+handling begins.
+
+</p>
+<p>
+
+In the default directory structure for a new webmachine application,
+the dispatch terms will be in file:consult form in
+"priv/dispatch.conf" under the application root.
+
+</p>
+<h3 id="examples">Examples</h3>
+
+<p>
+
+The examples below are taken from
+<a href="http://www.erlang-factory.com/conference/SFBayAreaErlangFactory2009/speakers/justinsheehy">Justin Sheehy's slide at Erlang Factory 2009</a>
+</p>
+
+<table><tr><th>Dispatch Rule</th><th>URL</th><th>wrq:disp_path</th><th>wrq:path</th><th>wrq:path_info</th><th>wrq:path_tokens</th></tr>
+<tr><td>{["a"],           some_resource, []}</td><td>/a</td><td>""</td><td>"/a"</td><td>[]</td><td>[]</td></tr>
+
+<tr><td>{["a", '*'],      some_resource, []}</td><td>/a</td><td>""</td><td>"/a"</td><td>[]</td><td>[]</td></tr>
+<tr><td>{["a", '*'],      some_resource, []}</td><td>/a/b/c</td><td>"b/c"</td><td>"/a/b/c"</td><td>[]</td><td>["b", "c"]</td></tr>
+<tr><td>{["a", foo],      some_resource, []}</td><td>/a/b</td><td>""</td><td>"/a/b"</td><td>[{foo, "b"}]</td><td>[]</td></tr>
+
+<tr><td>{["a", foo, '*'], some_resource, []}</td><td>/a/b</td><td>""</td><td>"/a/b"</td><td>[{foo, "b"}]</td><td>[]</td></tr>
+<tr><td>{["a", foo, '*'], some_resource, []}</td><td>/a/b/c/d</td><td>"c/d"</td><td>"/a/b/c/d"</td><td>[{foo, "b"}]</td><td>["c", "d"]</td></tr>
+</table>
+
+<p>Query strings are easy too:</p>
+
+<ul><li>Given rule: {["a", foo, '*'], some_resource, []}
+</li><li>And URL: /a/b/c/d?fee=ah&amp;fie=ha
+</li><li>Then wrq:get_qs_value("fie",ReqData) -&gt; "ha"
+</li></ul>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine documentation" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine documentation</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>documentation</h3>
+
+<p>
+There are a lot of places you can choose to start reading about
+Webmachine.  A few of your options are:
+</p>
+
+<ul>
+ <li><a href="quickstart.html">get started right away</a></li>
+ <li><a href="example_resources.html">read some examples</a></li>
+ <li><a href="mechanics.html">understand Webmachine's execution model</a></li>
+ <li><a href="dispatcher.html">configure your URL dispatching</a></li>
+ <li><a href="resources.html">learn about the functions that can make up a resource</a></li>
+ <li><a href="reqdata.html">see how your resource can access the HTTP Request</a></li>
+ <li><a href="http://blog.therestfulway.com/2009/05/video-slideshow-introducing-webmachine.html">watch a video</a></li>
+ <li><a href="http://lists.therestfulway.com/mailman/listinfo/webmachine_lists.therestfulway.com">join the mailing list</a></li>
+ <li><a href="debugging.html">debug your application </a></li>
+ <li><a href="blogs.html">check out some blogs </a></li>
+</ul>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/example_resources.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine examples" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine examples</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine examples</h3>
+
+<p>
+The simplest possible example is the one produced via the
+<a href="quickstart.html">quickstart</a>.
+</p>
+<p>
+For an example of a read/write filesystem server showing several
+interesting features and supporting GET, PUT, DELETE, and POST, see
+<a href="http://bitbucket.org/justin/webmachine/src/tip/demo/src/demo_fs_resource.erl">demo_fs_resource</a>.
+</p>
+<p>
+For a very simple resource demonstrating content negotiation, basic
+auth, and some caching headers, see
+<a href="http://bitbucket.org/justin/webmachine/src/tip/demo/src/webmachine_demo_resource.erl">webmachine_demo_resource</a>.
+</p>
+<p>
+Some example code based on webmachine_demo_resource follows.
+</p>
+<p>
+The simplest working resource could export only one function in
+addition to init/1:
+</p>
+
+<pre>
+-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}.
+</pre>
+
+<p>
+That's really it -- a working webmachine resource. That resource will
+respond to all valid GET requests with the exact same response.
+</p>
+<p>
+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.
+</p>
+<p>
+Suppose I wanted to serve a plaintext client as well. I could note
+that I provide more than just HTML:
+</p>
+
+<pre>
+content_types_provided(ReqData, Context) ->
+   {[{"text/html", to_html},{"text/plain",to_text}], ReqData, Context}.
+</pre>
+
+<p>
+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)
+</p>
+
+<pre>
+to_text(ReqData, Context) ->
+    Path = wrq:disp_path(ReqData),
+    Body = io_lib:format("Hello ~s from webmachine.~n", [Path]),
+    {Body, ReqData, Context}.
+</pre>
+
+<p>
+Now that this resource provides multiple media types, it automatically performs conneg:
+</p>
+
+<pre>
+$ 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.
+</pre>
+
+<p>
+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:
+</p>
+
+<pre>
+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.
+</pre>
+
+<p>
+With that function in the resource, all paths except
+<code>/authdemo</code> 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.
+</p>
+<p>
+If you've generated the application from the
+<a href="quickstart.html">quickstart</a>, make sure
+you've added this line to your dispatch.conf file:
+</p>
+<pre>
+{["demo", '*'], mywebdemo_resource, []}.
+</pre>
+<p>
+Now you can point your browser at
+<code>http://localhost:8000/demo/authdemo</code> with the demo app running:
+</p>
+
+<pre>
+$ curl -v http://localhost:8000/demo/authdemo
+&gt; GET /demo/authdemo HTTP/1.1
+&gt; Host: localhost:8000
+&gt; Accept: */*
+&gt; 
+&lt; HTTP/1.1 401 Unauthorized
+&lt; WWW-Authenticate: Basic realm=webmachine
+&lt; Server: MochiWeb/1.1 WebMachine/0.97
+&lt; Date: Sun, 15 Mar 2009 02:57:43 GMT
+&lt; Content-Length: 0
+
+&lt; 
+</pre>
+<p></p>
+<pre>
+$ curl -v -u authdemo:demo1 http://localhost:8000/demo/authdemo 
+* Server auth using Basic with user 'authdemo'
+&gt; GET /demo/authdemo HTTP/1.1
+&gt; Authorization: Basic YXV0aGRlbW86ZGVtbzE=
+&gt; Host: localhost:8000
+&gt; Accept: */*
+&gt; 
+&lt; HTTP/1.1 200 OK
+&lt; Vary: Accept
+&lt; Server: MochiWeb/1.1 WebMachine/0.97
+
+&lt; Date: Sun, 15 Mar 2009 02:59:02 GMT
+&lt; Content-Type: text/html
+&lt; Content-Length: 59
+&lt; 
+&lt;html&gt;&lt;body&gt;Hello authdemo from webmachine.
+&lt;/body&gt;&lt;/html&gt;
+</pre>
+
+<p>
+HTTP caching support is also quite easy, with functions allowing
+resources to define (e.g.) <code>last_modified</code>,
+<code>expires</code>, and <code>generate_etag.</code> 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:
+</p>
+
+<pre>
+generate_etag(ReqData, Context) -> {wrq:raw_path(ReqData), ReqData, Context}.
+</pre>
+
+<p>Similarly, here's a trivial expires rule:</p>
+
+<pre>
+expires(ReqData, Context) -> {{{2021,1,1},{0,0,0}}, ReqData, Context}.
+</pre>
+
+<p>
+And now the response from our earlier request is appropriately tagged:
+</p>
+
+<pre>
+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
+
+&lt;html&gt;&lt;body&gt;Hello authdemo from webmachine.
+&lt;/body&gt;&lt;/html&gt;
+</pre>
+
+<p>
+For more details, read the source of the resources linked at the top
+of this page.
+</p>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/favicon.ico

Added
New image

www/images/WM200-crop.png

Added
New image

www/images/basho-landscape.gif

Added
New image

www/images/basic-trace-decision-tab.png

Added
New image

www/images/basic-trace-labeled.png

Added
New image

www/images/basic-trace-request-tab.png

Added
New image

www/images/basic-trace-response-tab.png

Added
New image

www/images/bg.gif

Added
New image

www/images/blankbox.gif

Added
New image

www/images/chash.gif

Added
New image

www/images/easy-ops.gif

Added
New image

www/images/gossip4.gif

Added
New image

www/images/halfblankbox.gif

Added
New image

www/images/http-headers-status-v3.png

Added
New image

www/images/more.gif

Added
New image

www/images/site.gif

Added
New image

www/images/splash250.gif

Added
New image

www/images/vclock.gif

Added
New image
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine - software shaped like the Web - basho technologies" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style.css" type="text/css" />
+	<title>Webmachine - software shaped like the Web</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a class="current" href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		
+		<div id="intro">
+			<p>Webmachine is not much like the Web frameworks you're used to. You can call Webmachine a REST toolkit if you like, and we won't argue with you.</p>
+		</div>
+		<div id="left">
+<p>
+Webmachine is an application layer that adds HTTP semantic awareness on top of the excellent bit-pushing and HTTP syntax-management provided by
+<a href="http://code.google.com/p/mochiweb/">mochiweb</a>,
+and provides a simple and clean way to connect that to your
+application's behavior.
+</p>
+<p>
+A Webmachine application is a set of resources, each of which is a set of
+<a href="resources.html">functions</a> over the state of the resource. We really mean functions here, not object-methods, infinite-server-loops, or any other such construction. This aspect of Webmachine is one of the reasons why Webmachine applications are relatively easy to understand and extend.
+</p>
+<p>
+These functions give you a place to define the representations and other Web-relevant properties of your application's resources -- with the emphasis that the first-class things on the Web are resources and that their essential properties of interaction are already quite well defined and usefully constrained.
+</p>
+<p>
+For most Webmachine applications, most of the functions are quite small and isolated. One of the nice effects of this is that a quick reading of a resource will give you an understanding of the application, its Web behavior, and the relationship between them. Since these functions are usually <a href="reftrans.html">referentially transparent</a>, Webmachine applications can be quite easy to test. There's no need for mock objects, fake database connections, or any other wastes of time when you can write tests against each component of your application in terms of the input and output to various functions.
+</p>
+<p>
+We believe that by giving Web developers a
+<a href="mechanics.html">system</a> with conventions that
+<a href="diagram.html">directly map to HTTP</a>
+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.
+</p>			
+		</div>
+		<div id="right">
+			<h3>more information</h3>
+			<ul>
+				<li><a href="intros.html">introduction</a></li>
+				<li><a href="docs.html">documentation</a></li>
+				<li><a href="blogs.html">other writing</a></li>
+			</ul>
+                        <a href="diagram.html"><img src="images/WM200-crop.png" alt="Webmachine Diagram" /></a>
+                        <a href="http://www.basho.com"><img src="images/basho-landscape.gif" alt="Basho" /></a>
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine introductions" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>introductions to Webmachine</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>How do I get started?</h3>
+
+<p>
+If you want to jump in and start coding right away, the
+<a href="quickstart.html">quickstart</a> is the way to go.
+</p>
+<p>
+If you would prefer to watch a narrated slideshow introduction, this is roughly similar to the presentation that was given at
+<a href="http://www.erlang-factory.com/conference/SFBayAreaErlangFactory2009">Bay Area Erlang Factory 2009</a>:
+</p>
+
+<object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.40" /><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" VALUE="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=13693397&vid=5178506&lang=en-us&intl=us&thumbUrl=http%3A//l.yimg.com/a/p/i/bcst/videosearch/9129/86376656.jpeg&embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.40" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" AllowScriptAccess="always" bgcolor="#000000" flashVars="id=13693397&vid=5178506&lang=en-us&intl=us&thumbUrl=http%3A//l.yimg.com/a/p/i/bcst/videosearch/9129/86376656.jpeg&embed=1" ></embed></object>
+
+<p>
+Some <a href="blogs.html">blogs</a> also have posts that can serve as
+useful introductions to Webmachine, if you prefer to start that way.
+</p>
+
+<p>
+No matter how you get started, you'll probably want to come back and
+read <a href="docs.html">more documentation</a> once you get up and running.
+<p>
+
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/mechanics.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine mechanics" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine mechanics</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>How does this Webmachine thing work, anyway?</h3>
+
+<p>
+This page describes 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.
+</p>
+<p>
+(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 help you make sure that your app's presence on
+the Web is well-behaved and well-structured.)
+</p>
+<p>
+When a request is initially received by Webmachine it is handled by the
+<a href="dispatcher.html">dispatcher</a>.
+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
+<a href="reqdata.html">request data record</a>
+is created and the matching
+<a href="resources.html">resource</a> is
+kicked off via its <code>init/1</code> function.
+</p>
+<p>
+The resource then flows through the decision core, which is
+effectively just running the request through the
+<a href="diagram.html">HTTP flowchart</a>.  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 <code>C3</code> depends purely on whether the client sent
+an <code>Accept</code> header.  In many cases, however, the decision
+is application-specific -- the path from <code>B10</code> depends on
+the value the
+<a href="resources.html">resource</a> module
+returns from <code>allowed_methods.</code> 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.
+</p>
+<p>
+Most of the time you don't need to worry about this big diagram,
+though -- just define the
+<a href="resources.html">resource functions</a>
+relevant to your app and Webmachine will do the rest.  A
+good understanding of this central mechanism in Webmachine is most
+useful when
+<a href="debugging.html">debugging your resources</a>.
+</p>
+<p>
+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.
+</p>
+<p>
+A useful way to build Webmachine applications is often just to write a
+single function such as <code>to_html</code> to provide the most
+basic of stubs; when that function exists (or any other returned by
+<code>content_types_provided</code>) you can produce <code>200 OK</code>
+responses.  After that, you can easily extend your
+application's Web behavior simply by filling in the other
+<a href="resources.html">resource functions</a> as desired.
+</p>
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/quickstart.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="getting started quickly with Webmachine" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>getting started quickly with Webmachine</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>getting started quickly with Webmachine</h3>
+
+
+<p>Make sure that you have a working Erlang/OTP release, R12B5 or later.</p>
+
+<p>Get the webmachine code:</p>
+
+<p><pre>
+hg clone http://bitbucket.org/justin/webmachine/ webmachine-read-only
+</pre></p>
+
+<p>Build webmachine:</p>
+
+<p><pre>
+cd webmachine-read-only
+make
+</pre></p>
+
+<p>Create, build, and start the skeleton resource:</p>
+
+<p><pre>
+./scripts/new_webmachine.erl mywebdemo /tmp
+cd /tmp/mywebdemo
+make
+./start.sh
+</pre></p>
+
+<p>Take a look! Point a web browser at <a href="http://localhost:8000/">http://localhost:8000/</a></p>
+
+<p>To make this resource handle URI paths other than /, add more
+<a href="dispatcher.html">dispatch</a> terms in
+/tmp/mywebdemo/priv/dispatch.conf; to make that resource to more
+interesting things, modify the
+<a href="resources.html">resource</a> itself
+at /tmp/mywebdemo/src/mywebdemo_resource.erl.</p>
+
+<p>To learn how to do more interesting things, check out <a href="example_resources.html">some examples</a> or read <a href="docs.html">more documentation</a>.</p>
+
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/reftrans.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine's approach to resource functions and referential transparency" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine's approach to resource functions and referential transparency</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine's approach to resource functions and referential transparency</h3>
+
+<p>
+Webmachine goes to great lengths to help your <a href="resources.html">resource functions</a> to be as referentially transparent as possible.  By "referentially transparent" we mean that given the same input <code> {ReqData, Context} </code> the function will return the same output <code> {Result, ReqData, Context} </code> and that side effects will be insignificant from the point of view of Webmachine's execution.
+</p>
+<p>
+We don't try to force you into pure referential transparency; we give you as big a hole as you want via <code>Context</code>.  As that term is application-specific, you can put database handles, server process identifiers, or anything else you like in there and we won't try to stop you.
+</p>
+<p>
+However, all Webmachine really cares about is the rest of the terms.  Since resource functions are generally referentially transparent at least with regard to those terms, many things are easier -- testing, <a href="debugging.html">debugging</a>, and even static analysis and reasoning about your Web application.
+</p>
+<p>
+Note that there is one important exception to this.  The <a href="streambody.html">streamed body feature</a> exists to allow resources to consume or produce request/response bodies a hunk at a time without ever having the whole thing in memory.  While the continuation-passing style used in the streaming API is friendly to general functional analysis, due to the necessary side-effect of reading or writing to sockets the stream bodies cannot be treated in quite the same way as other uses of the <code>ReqData</code> interface.  Luckily, it is easy to inspect a <code>ReqData</code> to see if this is the case in any individual resource or request instance.
+</p>
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine request/response data" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine request/response data</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine request/response data</h3>
+
+<p>
+
+This is documentation of the Webmachine Request Data API as embodied
+by the <code>"wrq"</code> module.  This module is the means by which
+resources access and manipulate the state of the request they are
+handling.
+
+</p>
+<p>
+
+Given that all webmachine resource functions have this signature:
+
+</p>
+
+<span class="fwf">f(ReqData, Context) -> {Result, ReqData, Context}</span>
+
+<p>
+
+we should explain in detail the <code>ReqData</code> input and output
+parameter.  This is a data structure used to represent the request
+sent by the client as well as the response being built by the
+resource.  The <code>wrq</code> module is used to access the values in
+the input parameter.  Most functions in most resources have no need to
+modify the output <code>ReqData</code> and can simply pass along the
+one received as input.  However, in some cases a resource will need to
+make some update to the response other than that implied by
+<code>Result</code> and in those cases it should use the
+<code>wrq</code> module to build a modified <code>ReqData</code> from
+the original one for the return value.
+
+</p>
+<p>
+
+A couple of nonstandard types are assumed here:
+
+</p>
+
+<table><tr><th>Type</th><th>Description</th></tr>
+<tr><td>string()</td><td>a list() with all elements in the ASCII range</td></tr>
+<tr><td>rd()</td><td>opaque record, used as the input/output <code>ReqData</code></td></tr>
+<tr><td>streambody()</td><td>A webmachine <a href="streambody.html">streamed body format</a></td></tr>
+<tr><td>mochiheaders()</td><td>a structure used in mochiweb for HTTP header storage</td></tr>
+</table>
+
+<p>The accessors are:</p>
+
+<table><tr><th>Function</th><th>Description</th></tr>
+<tr><td><code> method(rd()) -&gt; 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' </code></td><td>The HTTP method used by the client.  (note that it is an <code> atom() </code>)</td></tr>
+
+<tr><td><code> version(rd()) -&gt; {integer(),integer()} </code></td><td>The HTTP version used by the client.  Most often <code> {1,1} </code>.</td></tr>
+<tr><td><code> peer(rd()) -&gt; string() </code></td><td>The IP address of the client.</td></tr>
+<tr><td><code> disp_path(rd()) -&gt; string() </code></td><td>The "local" path of the resource URI; the part after any prefix used in <a href="dispatcher.html">dispatch configuration</a>.  Of the three path accessors, this is the one you usually want.  This is also the one that will change after <code>create_path</code> is called in your <a href="resources.html">resource</a>.</td></tr>
+
+<tr><td><code> path(rd()) -&gt; string() </code></td><td>The path part of the URI -- after the host and port, but not including any query string.</td></tr>
+<tr><td><code> raw_path(rd()) -&gt; string() </code></td><td>The entire path part of the URI, including any query string present.</td></tr>
+<tr><td><code> path_info(atom(),rd()) -&gt; 'undefined' | string() </code></td><td>Looks up a binding as described in <a href="dispatcher.html">dispatch configuration</a>.</td></tr>
+
+<tr><td><code> path_info(rd()) -&gt; any() </code></td><td>The dictionary of bindings as described in <a href="dispatcher.html">dispatch configuration</a>.</td></tr>
+<tr><td><code> path_tokens(rd()) -&gt; list() </code></td><td>This is a list of <code> string() </code> terms, the disp_path components split by "/".</td></tr>
+
+<tr><td><code> get_req_header(string(),rd()) -&gt; 'undefined' | string() </code></td><td>Look up the value of an incoming request header.</td></tr>
+<tr><td><code> req_headers(rd()) -&gt; mochiheaders() </code></td><td>The incoming HTTP headers.  Generally, get_req_header is more useful.</td></tr>
+<tr><td><code> req_body(rd()) -&gt; 'undefined' | binary() </code></td><td>The incoming request body, if any.</td></tr>
+
+<tr><td><code> stream_req_body(rd(),integer()) -&gt; streambody() </code></td><td>The incoming request body in <a href="streambody.html">streamed</a> form, with hunks no bigger than the integer argument.</td></tr>
+<tr><td><code> get_cookie_value(string(),rd()) -&gt; string() </code></td><td>Look up the named value in the incoming request cookie header.</td></tr>
+<tr><td><code> req_cookie(rd()) -&gt; string() </code></td><td>The raw value of the cookie header.  Note that get_cookie_value is often more useful.</td></tr>
+
+<tr><td><code> get_qs_value(string(),rd()) -&gt; 'undefined' | string() </code></td><td>Given the name of a key, look up the corresponding value in the query string.</td></tr>
+<tr><td><code> get_qs_value(string(),string(),rd()) -&gt; string() </code></td><td>Given the name of a key and a default value if not present, look up the corresponding value in the query string.</td></tr>
+<tr><td><code> req_qs(rd()) -&gt; [{string(), string()}] </code></td><td>The parsed query string, if any.  Note that get_qs_value is often more useful.</td></tr>
+
+<tr><td><code> get_resp_header(string(),rd()) -&gt; string() </code></td><td>Look up the current value of an outgoing request header.</td></tr>
+<tr><td><code> resp_redirect(rd()) -&gt; bool() </code></td><td>the last value passed to do_redirect, false otherwise -- if true, then some responses will be 303 instead of 2xx where applicable</td></tr>
+<tr><td><code> resp_headers(rd()) -&gt; mochiheaders() </code></td><td>The outgoing HTTP headers.  Generally, get_resp_header is more useful.</td></tr>
+
+<tr><td><code> resp_body(rd()) -&gt; 'undefined' | binary() </code></td><td>The outgoing response body, if one has been set.  Usually, append_to_response_body is the best way to set this.</td></tr>
+<tr><td><code> app_root(rd()) -&gt; string() </code></td><td>Indicates the "height" above the requested URI that this resource is dispatched from.  Typical values are <code> "." </code>, <code> ".." </code>, <code> "../.." </code> and so on.</td></tr>
+
+</table>
+
+
+<p
+>The functions for (nondestructive) modification of <code> rd() </code> terms are:
+</p>
+
+
+<table><tr><th>Function</th><th>Description</th></tr>
+<tr><td><code> set_resp_header(string(),string(),rd()) -&gt; rd() </code></td><td>Given a header name and value, set an outgoing request header to that value.</td></tr>
+<tr><td><code> append_to_response_body(binary(),rd()) -&gt; rd() </code></td><td>Append the given value to the body of the outgoing response.</td></tr>
+
+<tr><td><code> do_redirect(bool(),rd()) -&gt; rd() </code></td><td>see resp_redirect; this sets that value.</td></tr>
+<tr><td><code> set_disp_path(string(),rd()) -&gt; rd() </code></td><td>The disp_path is the only path that can be changed during a request.  This function will do so.</td></tr>
+<tr><td><code> set_req_body(binary(),rd()) -&gt; rd() </code></td><td>Replace the incoming request body with this for the rest of the processing.</td></tr>
+
+<tr><td><code> set_resp_body(binary(),rd()) -&gt; rd() </code></td><td>Set the outgoing response body to this value.</td></tr>
+<tr><td><code> set_resp_body(streambody(),rd()) -&gt; rd() </code></td><td>Use this <a href="streambody.html">streamed body</a> to produce the outgoing response body on demand.</td></tr>
+<tr><td><code> set_resp_headers([{string(),string()}],rd()) -&gt; rd() </code></td><td>Given a list of two-tuples of {headername,value}, set those outgoing response headers.</td></tr>
+
+<tr><td><code> remove_resp_header(string(),rd()) -&gt; rd() </code></td><td>Remove the named outgoing response header.</td></tr>
+</table>
+
+		
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/resources.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine resource functions" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine resource functions</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine resource functions</h3>
+
+<p>All webmachine resources should include the webmachine resource library:</p>
+
+<p>
+<span class="fwf">	
+-include_lib("webmachine/include/webmachine.hrl").
+</span>
+</p>
+
+<p>
+All webmachine resources should define and export <span class="fwf">init/1</span>, which will receive a configuration property list from the <a href="dispatcher.html">dispatcher</a> as its argument. This function should, if successful, return <span class="fwf">{ok, Context}</span>. Context is any term, and will be threaded through all of the other webmachine resource functions.  Alternately, the resource can go into debugging mode by returning <span class="fwf">{{trace, Dir}, Context}</span> instead -- see <a href="debugging.html">the tracing documentation</a> for more information.</p>
+
+<p>All webmachine resource functions are of the signature:</p>
+
+<p>
+<span class="fwf">
+f(ReqData, Context) -> {Result, ReqData, Context}
+</span>
+</p>
+
+
+<p>
+<span class="fwf">Context</span> is an arbitrary <span class="fwf">term()</span> that is specific to your application.  Webmachine will never do anything with this term other than threading it through the various functions of your resource.  This is the means by which transient application-specific request state is passed along between functions.
+</p>
+<p>
+<span class="fwf">ReqData</span> is a <span class="fwf">#wm_reqdata{}</span> term, and is manipulated via the <a href="reqdata.html">wrq</a> interface.  A resource function may access request data (such as header values) from the input value.  If a resource function wishes to affect the response data in some way other than that implied by its return value (e.g. adding an X-Header) then it should modify the returned <span class="fwf">ReqData</span> term accordingly.
+</p>
+<p>
+The rest of this document is about the effects produced by different values in the <span class="fwf">Result</span> term.
+</p>
+<p>
+There are over 30 resource functions you can define, but any of them can be omitted as they have reasonable defaults.
+</p>
+<p>
+Each function is described below, showing the default and allowed values that may be in the <span class="fwf">Result</span> term. The default will be used if a resource does not export the function.  If a function has an "X" in the "Halt" column, it also has the option of returning either of the two following special values for <span class="fwf">Result</span>:
+
+</p>
+
+<table><tr><th>Result</th><th>Effect</th></tr>
+<tr><td class="fwf lhcol">{error, Err::term()}</td><td>Immediately end processing of this request, returning a 500 response code.  The response body will contain the <span class="fwf"> Err </span> term.</td></tr>
+<tr><td class="fwf lhcol">{halt, Code::integer()}</td><td>Immediately end processing of this request, returning response code Code.  It is the responsibility of the resource to ensure that all necessary response header and body elements are filled in <span class="fwf"> ReqData </span> in order to make that reponse code valid.</td></tr>
+</table>
+
+<p>
+Any function which has no description is optional and the effect of its return value should be evident from examining the <a href="diagram.html">diagram</a>.
+</p>
+
+<table>
+<tr><th>Function</th><th>Default</th><th>Halt</th><th>Allowed</th><th>Description</th></tr>
+
+<tr><td class="fwf">resource_exists</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td>Returning non-true values will result in 404 Not Found.</td></tr>
+
+<tr><td class="fwf">service_available</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">is_authorized</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> AuthHead</td><td>If this returns anything other than true, the response will be 401 Unauthorized. The AuthHead return value will be used as the value in the WWW-Authenticate header.</td></tr>
+
+<tr><td class="fwf">forbidden</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">allow_missing_post</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td>If the resource accepts POST requests to nonexistent resources, then this should return true.</td></tr>
+
+<tr><td class="fwf">malformed_request</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">uri_too_long</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">known_content_type</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+
+<tr><td class="fwf">valid_content_headers</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">valid_entity_length</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">options</td><td class="fwf">[]</td><td></td><td class="fwf">[Header]</td><td>If the OPTIONS method is supported and is used, the return value of this function is expected to be a list of pairs representing header names and values that should appear in the response.</td></tr>
+
+<tr><td class="fwf">allowed_methods</td><td class="fwf">['GET', 'HEAD']</td><td></td><td class="fwf">[Method]</td><td>If a Method not in this list is requested, then a 405 Method Not Allowed will be sent. Note that these are all-caps and are atoms. (single-quoted)</td></tr>
+<tr><td class="fwf">delete_resource</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td>This is called when a DELETE request should be enacted, and should return true if the deletion succeeded.</td></tr>
+<tr><td class="fwf">delete_completed</td><td class="fwf">true</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td>This is only called after a successful delete_resource call, and should return false if the deletion was accepted but cannot yet be guaranteed to have finished.</td></tr>
+
+<tr><td class="fwf">post_is_create</td><td class="fwf">false</td><td></td><td class="fwf">true <span class="fwf">|</span> false</td><td>If POST requests should be treated as a request to put content into a (potentially new) resource as opposed to being a generic submission for processing, then this function should return true. If it does return true, then create_path will be called and the rest of the request will be treated much like a PUT to the Path entry returned by that call.</td></tr>
+<tr><td class="fwf">create_path</td><td class="fwf">undefined</td><td></td><td class="fwf">Path</td><td>This will be called on a POST request if post_is_create returns true. It is an error for this function to not produce a Path if post_is_create returns true.  The Path returned should be a valid URI part following the dispatcher prefix. That Path will replace the previous one in the return value of <span class="fwf"> wrq:disp_path(ReqData) </span> for all subsequent resource function calls in the course of this request.</td></tr>
+
+<tr><td class="fwf">process_post</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td>If post_is_create returns false, then this will be called to process any POST requests. If it succeeds, it should return true.</td></tr>
+<tr><td class="fwf">content_types_provided</td><td><span class="fwf"> [{"text/html", to_html}] </span></td><td></td><td><span class="fwf"> [{Mediatype, Handler}] </span></td><td>This should return a list of pairs where each pair is of the form <span class="fwf"> {Mediatype, Handler} </span> where <span class="fwf">Mediatype</span> is a string of content-type format and the <span class="fwf">Handler</span> is an atom naming the function which can provide a resource representation in that media type.  Content negotiation is driven by this return value. For example, if a client request includes an Accept header with a value that does not appear as a first element in any of the return tuples, then a 406 Not Acceptable will be sent.</td></tr>
+
+<tr><td class="fwf">content_types_accepted</td><td><span class="fwf"> [] </span></td><td></td><td><span class="fwf"> [{Mediatype, Handler}] </span></td><td>This is used similarly to content_types_provided, except that it is for incoming resource representations -- for example, PUT requests. Handler functions usually want to use <span class="fwf"> wrq:req_body(ReqData) </span> to access the incoming request body.</td></tr>
+<tr><td class="fwf">charsets_provided</td><td class="fwf">no_charset</td><td></td><td>no_charset <span class="fwf">|</span> <span class="fwf"> [{Charset, CharsetConverter}] </span></td><td>If this is anything other than the atom no_charset, it must be a list of pairs where each pair is of the form Charset, Converter where Charset is a string naming a charset and Converter is a callable function in the resource which will be called on the produced body in a GET and ensure that it is in Charset.</td></tr>
+
+<tr><td class="fwf">encodings_provided</td><td><span class="fwf"> [{"identity", fun(X) -&gt; X end}] </span></td><td></td><td><span class="fwf"> [{Encoding, Encoder}] </span></td><td>This must be a list of pairs where in each pair Encoding is a string naming a valid content encoding and Encoder is a callable function in the resource which will be called on the produced body in a GET and ensure that it is so encoded.  One useful setting is to have the function check on method, and on GET requests return <span class="fwf"> [{"identity", fun(X) -&gt; X end}, {"gzip", fun(X) -&gt; zlib:gzip(X) end}] </span> as this is all that is needed to support gzip content encoding.</td></tr>
+
+<tr><td class="fwf">variances</td><td><span class="fwf"> [] </span></td><td></td><td><span class="fwf"> [HeaderName] </span></td><td>If this function is implemented, it should return a list of strings with header names that should be included in a given response's Vary header. The standard conneg headers (Accept, Accept-Encoding, Accept-Charset, Accept-Language) do not need to be specified here as Webmachine will add the correct elements of those automatically depending on resource behavior.</td></tr>
+<tr><td class="fwf">is_conflict</td><td class="fwf">false</td><td></td><td class="fwf">true <span class="fwf">|</span> false</td><td>If this returns true, the client will receive a 409 Conflict.</td></tr>
+<tr><td class="fwf">multiple_choices</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td>If this returns true, then it is assumed that multiple representations of the response are possible and a single one cannot be automatically chosen, so a 300 Multiple Choices will be sent instead of a 200.</td></tr>
+
+<tr><td class="fwf">previously_existed</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf">true <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">moved_permanently</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf"><span class="fwf"> {true, MovedURI} </span> <span class="fwf">|</span> false</td><td></td></tr>
+
+<tr><td class="fwf">moved_temporarily</td><td class="fwf">false</td><td align='center' class='x_check'>X</td><td class="fwf"><span class="fwf"> {true, MovedURI} </span> <span class="fwf">|</span> false</td><td></td></tr>
+<tr><td class="fwf">last_modified</td><td class="fwf">undefined</td><td></td><td class="fwf">undefined <span class="fwf">|</span> <span class="fwf"> {{YYYY,MM,DD}, {Hour,Min,Sec}} </span></td><td></td></tr>
+
+<tr><td class="fwf">expires</td><td class="fwf">undefined</td><td></td><td class="fwf">undefined <span class="fwf">|</span> <span class="fwf"> {{YYYY,MM,DD}, {Hour,Min,Sec}} </span></td><td></td></tr>
+<tr><td class="fwf">generate_etag</td><td class="fwf">undefined</td><td></td><td class="fwf">undefined <span class="fwf">|</span> ETag</td><td>If this returns a value, it will be used as the value of the ETag header and for comparison in conditional requests.</td></tr>
+<tr><td class="fwf">finish_request</td><td class="fwf">true</td><td></td><td class="fwf">true <span class="fwf">|</span> false</td><td>This function, if exported, is called just before the final response is constructed and sent.  The <span class="fwf"> Result </span> is ignored, so any effect of this function must be by returning a modified <span class="fwf"> ReqData </span>.</td></tr>
+
+<tr><td class="fwf">body-producing function named as a Handler by content_types_provided</td><td></td><td align='center' class='x_check'>X</td><td class="fwf"><span class="fwf"> Body </span></td><td>The Body should be either an <span class="fwf">iolist()</span> or <a href="streambody.html">{stream,streambody()}</a></td></tr>
+<tr><td class="fwf">POST-processing function named as a Handler by content_types_accepted</td><td></td><td align='center' class='x_check'>X</td><td class="fwf"><span class="fwf"> true </span></td><td></td></tr>
+</table>
+
+<p>
+The above are all of the supported predefined resource functions. In addition to whichever of these a resource wishes to use, it also must export all of the functions named in the return values of the content_types_provided and content_types_accepted functions with behavior as described in the bottom two rows of the table.
+</p>
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");
+pageTracker._trackPageview();
+} catch(err) {}</script>
+
+</body>
+</html>
+

www/streambody.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta name="author" content="Basho Technologies" />
+	<meta name="description" content="Webmachine streamed bodies" />
+	<meta name="keywords" content="webmachine http rest web" />
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+	<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
+	<title>Webmachine streamed bodies</title>
+</head>
+<body>
+	<div id="content">
+		<h1><span class="hr"></span><a href="/">webmachine</a></h1>
+		<ul id="top">
+			<li><a href="/">Home</a></li>
+			<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
+                        <li><a href="contact.html">Contact</a></li>
+		</ul>
+		<div id="left">
+<h3>Webmachine streamed bodies</h3>
+
+<p>
+
+Webmachine allows the resource developer to handle request and
+response bodies as either whole units (binary or iolist) to be handed
+around at once, or else to choose to "stream" the body.
+
+</p>
+<p>
+
+The body-handling functions are:
+
+</p>
+
+<ul><li><code> wrq:req_body/1 </code>
+</li><li><code> wrq:stream_req_body/2 </code>
+</li><li><code> wrq:set_resp_body/2 </code>
+</li></ul>
+
+<p>
+
+The last of these, <code>wrq:set_resp_body/2</code>, is also called
+implicitly with the return value of any content-producing function
+such as <code>to_html/2</code>.
+
+</p>
+<p>
+
+The first of these (<code>req_body</code>) is the simplest.  It will
+provide the whole incoming request body as a binary.  (Unless the body
+is too large, as set by <code>wrq:set_max_recv_body/2</code> or
+defaulting to 50M) For the majority of resources, this is the easiest
+way to handle the incoming request body.
+
+</p>
+<p>
+
+If a resource wants to handle the incoming request body a hunk at a
+time, it may call <code>wrq:stream_req_body/2</code> instead.  Instead
+of a binary, this produces a <code>StreamBody</code> structure.
+
+</p>
+<p>
+
+(It is an error to call both <code>wrq:req_body/1</code> and
+<code>wrq:stream_req_body/2</code> in the execution of a single
+resource.)
+
+</p>
+<p>
+
+A <code>StreamBody</code> is a pair of the form
+<code>{Data,Next}</code> where <code>Data</code> is a binary and
+<code>Next</code> is either the atom <code>done</code> signifying the
+end of the body or else a 0-arity function that, when called, will
+produce the "next" <code>StreamBody</code> structure.
+
+</p>
+<p>
+
+The integer parameter to <code>wrq:stream_req_body/2</code> indicates
+the maximum size in bytes of any <code>Hunk</code> from the resulting
+<code>StreamBody</code>.
+
+</p>
+<p>
+
+When a resource provides a body to be sent in the response, it should
+use <code>wrq:set_resp_body/2</code>.  The parameter to this function
+may be either an iolist, representing the entire body, or else a pair
+of the form <code>{stream, StreamBody}</code>.
+
+</p>
+<p>
+
+An example may make the usage of this API clearer.  A complete and
+working resource module using this API in both directions:
+
+</p>
+<p>
+
+<pre>
+-module(mywebdemo_resource).
+-export([init/1, allowed_methods/2, process_post/2]).
+
+-include_lib("webmachine/include/webmachine.hrl").
+
+init([]) -> {ok, undefined}.
+
+allowed_methods(ReqData, State) -> {['POST'], ReqData, State}.
+
+process_post(ReqData, State) ->
+    Body = get_streamed_body(wrq:stream_req_body(ReqData, 3), []),
+    {true, wrq:set_resp_body({stream, send_streamed_body(Body,4)},ReqData), State}.
+
+send_streamed_body(Body, Max) ->
+    HunkLen=8*Max,
+    case Body of        
+        <<A:HunkLen,Rest/binary>> ->
+            io:format("SENT ~p~n",[<<A:HunkLen>>]),
+            {<<A:HunkLen>>, fun() -> send_streamed_body(Rest,Max) end};
+        _ ->
+            io:format("SENT ~p~n",[Body]),
+            {Body, done}
+    end.
+
+get_streamed_body({Hunk,done},Acc) ->
+    io:format("RECEIVED ~p~n",[Hunk]),
+    iolist_to_binary(lists:reverse([Hunk|Acc]));
+get_streamed_body({Hunk,Next},Acc) ->
+    io:format("RECEIVED ~p~n",[Hunk]),
+    get_streamed_body(Next(),[Hunk|Acc]).
+</pre>
+
+</p>
+<p>
+
+If you use this resource in place of the file
+<code>/tmp/mywebdemo/src/mywebdemo_resource.erl</code> in the
+<a href="quickstart.html">quickstart</a> setup, you should then be able
+to issue <code>curl -d '1234567890' http://127.0.0.1:8000/</code> on
+the command line and the <code>io:format</code> calls will show you
+what is going on.
+
+</p>
+<p>
+
+Obviously, a realistic resource wouldn't use this API just to collect
+the whole binary into memory or break one up that is already present
+-- you'd use <code>req_body</code> and put a simple iolist into
+<code>set_resp_body</code> instead.  Also, the choices of 3 and 4
+bytes as hunk size are far from optimal for most reasonable uses.
+This resource is intended only as a demonstration of the API, not as a
+real-world use of streaming request/response bodies.
+
+</p>
+
+		</div>
+		<div id="footer">
+
+		</div>
+	</div>
+
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-4979965-5");