<NME> a.markdown
<BEF> ADDFILE
<MSG> shuffle

<DFF> @@ -0,0 +1,68 @@
+Request Matchers
+----------------
+
+### Methods and Paths
+
+Unfiltered supplies a wide range of *request matchers*—extractor
+objects that work against requests—from path segments to HTTP methods
+and headers. Applications use request matchers to define whether and
+how they will respond to a request.
+
+    case GET(Path("/record/1")) => ...
+
+This case will match GET requests to the path `/record/1`. To match
+against path segments, we can nest one additional extractor:
+
+    case GET(Path(Seg("record" :: id :: Nil))) => ...
+
+This matches any `id` string that is directly under the record
+path. The `Seg` extractor object matches against the `String` type and
+it is typically nested under a `Path` matcher. `Seg` extracts a lists
+of strings from the supplied string, separated into path segments by
+forward-slashes.
+
+### Reading Requests and Delayed Matching
+
+The above case clause matches a request to get a record. What about
+putting them?
+
+    case req @ PUT(Path(Seg("record" :: id :: Nil))) =>
+      val bytes = Body.bytes(req)
+      ...
+
+Access to the request body generally has side effects, such as the
+consumption of a stream that can only be read once. For this reason
+the body is not accessed from a request matcher, which could be
+evaluated more than one time, but from utility functions that operate
+on the request object.
+
+In this case, we assigned a reference to the request using `req @` and
+then read its body into a byte array—on the assumption that its body
+will fit into available memory. That aside, a minor annoyance is that
+this code introduces some repetition in the matching expression.
+
+    case GET(Path(Seg("record" :: id :: Nil))) => ...
+    case req @ PUT(Path(Seg("record" :: id :: Nil))) => ...
+
+An alternative is to match first on the path, then on the method:
+
+    case req @ Path(Seg("record" :: id :: Nil)) => req match {
+      case GET(_) => ...
+      case PUT(_) => ...
+      case _ => ...
+    }
+
+This approach eliminates the duplicated code, but it's important to
+recognize that it behaves differently as well. The original intent
+partial function was simply *not defined* for request to that path
+that were not a GET or a PUT. The latest one matches any request to
+that path, and therefore it must return a value for all methods with
+its match expression.
+
+Importantly, delaying the match on request method simplified the
+intent partial function. What used to be two cases is now one, and we
+could add support for other methods like DELETE without adding any
+complexity to its pattern matching. This is worth noting because
+`ifDefined` is called on every intent at least once prior to its
+evaluation. By making the intent more broadly defined, we've reduced
+the complexity of that and potentially improved runtime performance.

{'commit': 'diff --git a/docs/00.markdown b/docs/00.markdown\nnew file mode 100644\nindex 00000000..319e8b2e\n--- /dev/null\n+++ b/docs/00.markdown\n@@ -0,0 +1,9 @@\n+Unfiltered\n+==========\n+\n+*Unfiltered* is a toolkit for servicing HTTP requests in Scala. It\n+ provides a consistent vocabulary for handing requests on various\n+ server backends, but does not interfere with direct access to their\n+ native interfaces.\n+\n+> [Version $version$ Release Notes](http://implicit.ly/unfiltered-$vrsn$)\ndiff --git a/docs/01.markdown b/docs/01.markdown\nindex 319e8b2e..b4e4d446 100644\n--- a/docs/01.markdown\n+++ b/docs/01.markdown\n@@ -1,9 +1,88 @@\n-Unfiltered\n-==========\n+Try Unfiltered\n+--------------\n \n-*Unfiltered* is a toolkit for servicing HTTP requests in Scala. It\n- provides a consistent vocabulary for handing requests on various\n- server backends, but does not interfere with direct access to their\n- native interfaces.\n+It\'s not hard to write a request handler in the Scala console using\n+Unfiltered. The tricky part is getting everything you need on the\n+classpath.\n \n-> [Version $version$ Release Notes](http://implicit.ly/unfiltered-$vrsn$)\n+### Play Project\n+\n+The approach recommended here uses [giter8][g8], a tool for setting up\n+projects based on templates stored in github. Assuming you don\'t have\n+giter8 installed and you are on a network-connected Linux or Mac, it\'s\n+easy to fix that.\n+\n+[g8]: https://github.com/n8han/giter8#readme\n+\n+    curl https://github.com/n8han/conscript/raw/master/setup.sh | sh\n+\n+That is [conscript][conscript]. Its `setup.sh` places a permanent\n+(assuming you don\'t delete it) executable script in `~/bin/cs`. At\n+some point you may want to add `~/bin` to your executable search path,\n+but these instructions will not assume it is.\n+\n+[conscript]: https://github.com/n8han/conscript#readme\n+\n+    ~/bin/cs n8han/giter8\n+\n+That installs a `g8`. Now you have a script to run giter8. The next\n+step creates a new project under the current working directory.\n+\n+    ~/bin/g8 softprops/unfiltered --name=justplayin\n+\n+Okay, finally we can use this project with sbt to get a console for\n+Unfiltered. You do have [sbt setup][sbt], don\'t you?\n+\n+[sbt]: http://code.google.com/p/simple-build-tool/wiki/Setup\n+\n+    cd justplayin\n+    sbt update console\n+\n+### Consoled\n+\n+Now that you have a `scala>` prompt with the `unfiltered-filter` and\n+`unfiltered-jetty` modules on the classpath, let\'s have some fun.\n+\n+    import unfiltered.request._\n+    import unfiltered.response._\n+    val echo = unfiltered.filter.Planify {\n+       case Path(Seg(p :: Nil)) => ResponseString(p)\n+    }\n+\n+This filter `echo` would work with any servlet container. We can\n+use it in a Jetty server right now.\n+\n+    unfiltered.jetty.Http.anylocal.filter(echo).run()\n+\n+The startup message tells you which open port was selected, and by\n+default it is only listening to requests from 127.0.0.1. So on the\n+same machine, you can make requests to your server. e.g.\n+\n+    curl http://127.0.0.1:<the right port>/hello+world\n+\n+Fancy desktop web browsers will work too. Notice that exactly one path\n+segment is required for the filter to respond to the request. If you\n+ask for the root path or a deeper path, the `echo` filter will\n+not handle the request and Jetty responds with a 404 page.\n+\n+If we want to handle any request, we could broaden the pattern\n+matching expression. (Press enter to stop the running server.)\n+\n+    val echoNice = unfiltered.filter.Planify {\n+       case Path(Seg(p :: Nil)) => ResponseString(p)\n+       case _ => ResponseString(\n+           "I can echo exactly one path element."\n+       )\n+    }\n+    unfiltered.jetty.Http.anylocal.filter(echoNice).run()\n+\n+Or we could define another filter chain it to the first.\n+\n+    val nice = unfiltered.filter.Planify {\n+       case _ => ResponseString(\n+           "I can echo exactly one path element."\n+       )\n+    }\n+    unfiltered.jetty.Http.anylocal.filter(echo).filter(nice).run()\n+\n+Happy now?\ndiff --git a/docs/02.markdown b/docs/02.markdown\nindex b4e4d446..7378d203 100644\n--- a/docs/02.markdown\n+++ b/docs/02.markdown\n@@ -1,47 +1,23 @@\n-Try Unfiltered\n---------------\n+Plans and Intents\n+-----------------\n \n-It\'s not hard to write a request handler in the Scala console using\n-Unfiltered. The tricky part is getting everything you need on the\n-classpath.\n+Unfiltered conditionally handles incoming requests using partial\n+functions. From the application\'s perspective, requests are\n+mapped to code paths by pattern matching. The library uses\n+a particular vocabulary to refer to the agents of this process\n+without ambiguity.\n \n-### Play Project\n+* An *intent* is a partial function for matching requests.\n+* A *plan* binds an intent to a particular server interface.\n \n-The approach recommended here uses [giter8][g8], a tool for setting up\n-projects based on templates stored in github. Assuming you don\'t have\n-giter8 installed and you are on a network-connected Linux or Mac, it\'s\n-easy to fix that.\n+For example, the `unfiltered.filter.Plan` trait extends the\n+`javax.servlet.Filter` interface. It declares an abstract `intent`\n+method for clients to define the intent partial function.\n \n-[g8]: https://github.com/n8han/giter8#readme\n+### Making Plans of Intents\n \n-    curl https://github.com/n8han/conscript/raw/master/setup.sh | sh\n-\n-That is [conscript][conscript]. Its `setup.sh` places a permanent\n-(assuming you don\'t delete it) executable script in `~/bin/cs`. At\n-some point you may want to add `~/bin` to your executable search path,\n-but these instructions will not assume it is.\n-\n-[conscript]: https://github.com/n8han/conscript#readme\n-\n-    ~/bin/cs n8han/giter8\n-\n-That installs a `g8`. Now you have a script to run giter8. The next\n-step creates a new project under the current working directory.\n-\n-    ~/bin/g8 softprops/unfiltered --name=justplayin\n-\n-Okay, finally we can use this project with sbt to get a console for\n-Unfiltered. You do have [sbt setup][sbt], don\'t you?\n-\n-[sbt]: http://code.google.com/p/simple-build-tool/wiki/Setup\n-\n-    cd justplayin\n-    sbt update console\n-\n-### Consoled\n-\n-Now that you have a `scala>` prompt with the `unfiltered-filter` and\n-`unfiltered-jetty` modules on the classpath, let\'s have some fun.\n+Looking back at the example on the previous page, you might wonder\n+where the plan ends and the intent begins.\n \n     import unfiltered.request._\n     import unfiltered.response._\n@@ -49,40 +25,20 @@ Now that you have a `scala>` prompt with the `unfiltered-filter` and\n        case Path(Seg(p :: Nil)) => ResponseString(p)\n     }\n \n-This filter `echo` would work with any servlet container. We can\n-use it in a Jetty server right now.\n-\n-    unfiltered.jetty.Http.anylocal.filter(echo).run()\n-\n-The startup message tells you which open port was selected, and by\n-default it is only listening to requests from 127.0.0.1. So on the\n-same machine, you can make requests to your server. e.g.\n-\n-    curl http://127.0.0.1:<the right port>/hello+world\n+In this case a plan is constructed directly from an anonymous partial\n+function—that function is the intent. We can define the same plan in\n+more explicit parts, as is usually necessary in a larger application.\n \n-Fancy desktop web browsers will work too. Notice that exactly one path\n-segment is required for the filter to respond to the request. If you\n-ask for the root path or a deeper path, the `echo` filter will\n-not handle the request and Jetty responds with a 404 page.\n-\n-If we want to handle any request, we could broaden the pattern\n-matching expression. (Press enter to stop the running server.)\n-\n-    val echoNice = unfiltered.filter.Planify {\n-       case Path(Seg(p :: Nil)) => ResponseString(p)\n-       case _ => ResponseString(\n-           "I can echo exactly one path element."\n-       )\n+    object Echo extends unfiltered.filter.Plan {\n+      def intent = {\n+        case Path(Seg(p :: Nil)) => ResponseString(p)\n+      }\n     }\n-    unfiltered.jetty.Http.anylocal.filter(echoNice).run()\n \n-Or we could define another filter chain it to the first.\n+Since this kind of plan is an implementation of the servlet filter\n+interface, we can pass it directly to a servlet container.\n \n-    val nice = unfiltered.filter.Planify {\n-       case _ => ResponseString(\n-           "I can echo exactly one path element."\n-       )\n-    }\n-    unfiltered.jetty.Http.anylocal.filter(echo).filter(nice).run()\n+    unfiltered.jetty.Http.anylocal.filter(Echo).run()\n \n-Happy now?\n+If a plan does not handle a request, the server may chain to the next\n+plan if there is one, or produce its own error response.\ndiff --git a/docs/03.markdown b/docs/03.markdown\nindex 7378d203..6a37fdb3 100644\n--- a/docs/03.markdown\n+++ b/docs/03.markdown\n@@ -1,44 +1,73 @@\n-Plans and Intents\n------------------\n+Bindings and Servers\n+--------------------\n \n-Unfiltered conditionally handles incoming requests using partial\n-functions. From the application\'s perspective, requests are\n-mapped to code paths by pattern matching. The library uses\n-a particular vocabulary to refer to the agents of this process\n-without ambiguity.\n+The core module unfiltered-library does not depend on or reference any\n+particular server backend. It defines internal abstractions for\n+requests and responses, with higher level abstractions on top.\n \n-* An *intent* is a partial function for matching requests.\n-* A *plan* binds an intent to a particular server interface.\n+An application or library that depends only on the core library could\n+be used with any backend that Unfiltered supports, but in most cases it\n+will depend on a *binding* module.\n \n-For example, the `unfiltered.filter.Plan` trait extends the\n-`javax.servlet.Filter` interface. It declares an abstract `intent`\n-method for clients to define the intent partial function.\n+### Binding Modules\n \n-### Making Plans of Intents\n+These bind Unfiltered\'s generic request and response interfaces to a\n+given implementation, as well as intent types and plan traits.\n \n-Looking back at the example on the previous page, you might wonder\n-where the plan ends and the intent begins.\n+#### Servlet Filters (unfiltered-filter)\n+\n+The Java Servlet API enables you to write applications that run on\n+servlet containers, anything from Tomcat to Google App Engine. Its\n+plan trait is a servlet filter.\n+\n+#### Netty Channels (unfiltered-netty)\n+\n+Netty defines *channels* for network I/O and implements them using\n+Java\'s Native I/O (NIO) interface. Its plan traits are upstream\n+channel handlers, and the module defines intents and plans in separate\n+`cycle` and `channel` subpackages, the former for traditional\n+request-response cycles and the latter for open-ended interaction.\n+\n+### Server Modules\n+\n+Server modules define runnable servers to execute your plans. They are\n+entirely optional. Applications can instead use Unfiltered\'s binding\n+modules with external containers, or they can interface directly with\n+server libraries.\n+\n+#### unfiltered-jetty\n+\n+Includes builders for Jetty servers that implement the HTTP and HTTPS\n+protocols. With this server it is particularly easy serve a web\n+browser interface for a local process. Unfiltered even gives you a\n+shortcut to open a browser window, if the user is on a 1.6+ JVM that\n+supports it.\n \n     import unfiltered.request._\n     import unfiltered.response._\n-    val echo = unfiltered.filter.Planify {\n-       case Path(Seg(p :: Nil)) => ResponseString(p)\n+    val hello = unfiltered.filter.Planify {\n+       case _ => ResponseString("hello world")\n+    }\n+    unfiltered.jetty.Http.anylocal.filter(hello).run { s =>\n+      unfiltered.util.Browser.open(\n+          "http://127.0.0.1:%d/".format(s.port)\n+      )\n     }\n \n-In this case a plan is constructed directly from an anonymous partial\n-function—that function is the intent. We can define the same plan in\n-more explicit parts, as is usually necessary in a larger application.\n+#### unfiltered-jetty-ajp\n \n-    object Echo extends unfiltered.filter.Plan {\n-      def intent = {\n-        case Path(Seg(p :: Nil)) => ResponseString(p)\n-      }\n-    }\n+A Jetty server configured for the [Apache JServ Protocol][ajp], a\n+binary protocol for proxying web requests.\n+\n+[ajp]: http://en.wikipedia.org/wiki/Apache_JServ_Protocol\n \n-Since this kind of plan is an implementation of the servlet filter\n-interface, we can pass it directly to a servlet container.\n+#### unfiltered-netty-server\n \n-    unfiltered.jetty.Http.anylocal.filter(Echo).run()\n+Bootstraps and binds a server for your channel handlers.\n \n-If a plan does not handle a request, the server may chain to the next\n-plan if there is one, or produce its own error response.\n+    import unfiltered.request._\n+    import unfiltered.response._\n+    val hello = unfiltered.netty.cycle.Planify {\n+       case _ => ResponseString("hello world")\n+    }\n+    unfiltered.netty.Http(8080).handler(hello).run()\ndiff --git a/docs/04.markdown b/docs/04.markdown\nindex 6a37fdb3..669a0ec1 100644\n--- a/docs/04.markdown\n+++ b/docs/04.markdown\n@@ -1,73 +1,51 @@\n-Bindings and Servers\n---------------------\n-\n-The core module unfiltered-library does not depend on or reference any\n-particular server backend. It defines internal abstractions for\n-requests and responses, with higher level abstractions on top.\n-\n-An application or library that depends only on the core library could\n-be used with any backend that Unfiltered supports, but in most cases it\n-will depend on a *binding* module.\n-\n-### Binding Modules\n-\n-These bind Unfiltered\'s generic request and response interfaces to a\n-given implementation, as well as intent types and plan traits.\n-\n-#### Servlet Filters (unfiltered-filter)\n-\n-The Java Servlet API enables you to write applications that run on\n-servlet containers, anything from Tomcat to Google App Engine. Its\n-plan trait is a servlet filter.\n-\n-#### Netty Channels (unfiltered-netty)\n-\n-Netty defines *channels* for network I/O and implements them using\n-Java\'s Native I/O (NIO) interface. Its plan traits are upstream\n-channel handlers, and the module defines intents and plans in separate\n-`cycle` and `channel` subpackages, the former for traditional\n-request-response cycles and the latter for open-ended interaction.\n-\n-### Server Modules\n-\n-Server modules define runnable servers to execute your plans. They are\n-entirely optional. Applications can instead use Unfiltered\'s binding\n-modules with external containers, or they can interface directly with\n-server libraries.\n-\n-#### unfiltered-jetty\n-\n-Includes builders for Jetty servers that implement the HTTP and HTTPS\n-protocols. With this server it is particularly easy serve a web\n-browser interface for a local process. Unfiltered even gives you a\n-shortcut to open a browser window, if the user is on a 1.6+ JVM that\n-supports it.\n-\n-    import unfiltered.request._\n-    import unfiltered.response._\n-    val hello = unfiltered.filter.Planify {\n-       case _ => ResponseString("hello world")\n-    }\n-    unfiltered.jetty.Http.anylocal.filter(hello).run { s =>\n-      unfiltered.util.Browser.open(\n-          "http://127.0.0.1:%d/".format(s.port)\n-      )\n-    }\n-\n-#### unfiltered-jetty-ajp\n-\n-A Jetty server configured for the [Apache JServ Protocol][ajp], a\n-binary protocol for proxying web requests.\n-\n-[ajp]: http://en.wikipedia.org/wiki/Apache_JServ_Protocol\n-\n-#### unfiltered-netty-server\n-\n-Bootstraps and binds a server for your channel handlers.\n-\n-    import unfiltered.request._\n-    import unfiltered.response._\n-    val hello = unfiltered.netty.cycle.Planify {\n-       case _ => ResponseString("hello world")\n-    }\n-    unfiltered.netty.Http(8080).handler(hello).run()\n+Project Setup\n+-------------\n+\n+### Modules and Artifacts\n+\n+Unfiltered\'s core, binding, server, and other modules are published\n+with references to their underlying dependencies, so that applications\n+need only explicitly depend on Unfiltered and other top-level\n+dependencies. Keep in mind that server modules and binding modules are\n+not generally co-dependent, so that if you are using for example\n+unfiltered-jetty, you will also need to specify unfiltered-filter.\n+\n+Each module is [cross-built][sbt] against several versions of Scala\n+and published to the [scala-tools][st] repository with the\n+organization-id "net.databinder". The modules have the Scala version\n+they are built against appended. For Scala $scala$, the full artifact\n+names are as follows:\n+\n+* unfiltered_$scala$\n+* unfiltered-filter_$scala$\n+* unfiltered-netty_$scala$\n+* unfiltered-websockets_$scala$\n+* unfiltered-jetty_$scala$\n+* unfiltered-jetty-ajp_$scala$\n+* unfiltered-netty-server_$scala$\n+* unfiltered-uploads_$scala$\n+* unfiltered-utils_$scala$\n+* unfiltered-spec_$scala$\n+* unfiltered-scalatest_$scala$\n+* unfiltered-json_$scala$\n+* unfiltered-scalate_$scala$\n+* unfiltered-oauth_$scala$\n+\n+[st]: http://scala-tools.org/repo-releases/net/databinder/\n+[sbt]: http://code.google.com/p/simple-build-tool/wiki/CrossBuild\n+\n+### Build Tools\n+\n+With **simple-build-tool** it\'s best to have the Scala version\n+[automatically appended][sbt] so it will always match your\n+project\'s. In a sbt 0.7.4 project:\n+\n+    val uf_filter = "net.databinder" %% "unfiltered-filter" % "$version$"\n+\n+For **Maven**, specify the full artifact name:\n+\n+    <dependency>\n+      <groupId>net.databinder</groupId>\n+      <artifactId>unfiltered-filter_$scala$</artifactId>\n+      <version>$version$</version>\n+    </dependency>\ndiff --git a/docs/05.markdown b/docs/05.markdown\nindex 669a0ec1..e1316931 100644\n--- a/docs/05.markdown\n+++ b/docs/05.markdown\n@@ -1,51 +1,9 @@\n-Project Setup\n--------------\n+Community\n+---------\n \n-### Modules and Artifacts\n+Unfiltered lives [on GitHub][gh], and many of its features and bug\n+fixes originate in forks of the project there. We also have [a mailing\n+list][nabble].\n \n-Unfiltered\'s core, binding, server, and other modules are published\n-with references to their underlying dependencies, so that applications\n-need only explicitly depend on Unfiltered and other top-level\n-dependencies. Keep in mind that server modules and binding modules are\n-not generally co-dependent, so that if you are using for example\n-unfiltered-jetty, you will also need to specify unfiltered-filter.\n-\n-Each module is [cross-built][sbt] against several versions of Scala\n-and published to the [scala-tools][st] repository with the\n-organization-id "net.databinder". The modules have the Scala version\n-they are built against appended. For Scala $scala$, the full artifact\n-names are as follows:\n-\n-* unfiltered_$scala$\n-* unfiltered-filter_$scala$\n-* unfiltered-netty_$scala$\n-* unfiltered-websockets_$scala$\n-* unfiltered-jetty_$scala$\n-* unfiltered-jetty-ajp_$scala$\n-* unfiltered-netty-server_$scala$\n-* unfiltered-uploads_$scala$\n-* unfiltered-utils_$scala$\n-* unfiltered-spec_$scala$\n-* unfiltered-scalatest_$scala$\n-* unfiltered-json_$scala$\n-* unfiltered-scalate_$scala$\n-* unfiltered-oauth_$scala$\n-\n-[st]: http://scala-tools.org/repo-releases/net/databinder/\n-[sbt]: http://code.google.com/p/simple-build-tool/wiki/CrossBuild\n-\n-### Build Tools\n-\n-With **simple-build-tool** it\'s best to have the Scala version\n-[automatically appended][sbt] so it will always match your\n-project\'s. In a sbt 0.7.4 project:\n-\n-    val uf_filter = "net.databinder" %% "unfiltered-filter" % "$version$"\n-\n-For **Maven**, specify the full artifact name:\n-\n-    <dependency>\n-      <groupId>net.databinder</groupId>\n-      <artifactId>unfiltered-filter_$scala$</artifactId>\n-      <version>$version$</version>\n-    </dependency>\n+[gh]: https://github.com/n8han/unfiltered\n+[nabble]: http://databinder.3617998.n2.nabble.com/Unfiltered-f5560764.html\ndiff --git a/docs/06.markdown b/docs/06.markdown\ndeleted file mode 100644\nindex e1316931..00000000\n--- a/docs/06.markdown\n+++ /dev/null\n@@ -1,9 +0,0 @@\n-Community\n----------\n-\n-Unfiltered lives [on GitHub][gh], and many of its features and bug\n-fixes originate in forks of the project there. We also have [a mailing\n-list][nabble].\n-\n-[gh]: https://github.com/n8han/unfiltered\n-[nabble]: http://databinder.3617998.n2.nabble.com/Unfiltered-f5560764.html\ndiff --git a/docs/06/a.markdown b/docs/06/a.markdown\nnew file mode 100644\nindex 00000000..d309bae6\n--- /dev/null\n+++ b/docs/06/a.markdown\n@@ -0,0 +1,68 @@\n+Request Matchers\n+----------------\n+\n+### Methods and Paths\n+\n+Unfiltered supplies a wide range of *request matchers*—extractor\n+objects that work against requests—from path segments to HTTP methods\n+and headers. Applications use request matchers to define whether and\n+how they will respond to a request.\n+\n+    case GET(Path("/record/1")) => ...\n+\n+This case will match GET requests to the path `/record/1`. To match\n+against path segments, we can nest one additional extractor:\n+\n+    case GET(Path(Seg("record" :: id :: Nil))) => ...\n+\n+This matches any `id` string that is directly under the record\n+path. The `Seg` extractor object matches against the `String` type and\n+it is typically nested under a `Path` matcher. `Seg` extracts a lists\n+of strings from the supplied string, separated into path segments by\n+forward-slashes.\n+\n+### Reading Requests and Delayed Matching\n+\n+The above case clause matches a request to get a record. What about\n+putting them?\n+\n+    case req @ PUT(Path(Seg("record" :: id :: Nil))) =>\n+      val bytes = Body.bytes(req)\n+      ...\n+\n+Access to the request body generally has side effects, such as the\n+consumption of a stream that can only be read once. For this reason\n+the body is not accessed from a request matcher, which could be\n+evaluated more than one time, but from utility functions that operate\n+on the request object.\n+\n+In this case, we assigned a reference to the request using `req @` and\n+then read its body into a byte array—on the assumption that its body\n+will fit into available memory. That aside, a minor annoyance is that\n+this code introduces some repetition in the matching expression.\n+\n+    case GET(Path(Seg("record" :: id :: Nil))) => ...\n+    case req @ PUT(Path(Seg("record" :: id :: Nil))) => ...\n+\n+An alternative is to match first on the path, then on the method:\n+\n+    case req @ Path(Seg("record" :: id :: Nil)) => req match {\n+      case GET(_) => ...\n+      case PUT(_) => ...\n+      case _ => ...\n+    }\n+\n+This approach eliminates the duplicated code, but it\'s important to\n+recognize that it behaves differently as well. The original intent\n+partial function was simply *not defined* for request to that path\n+that were not a GET or a PUT. The latest one matches any request to\n+that path, and therefore it must return a value for all methods with\n+its match expression.\n+\n+Importantly, delaying the match on request method simplified the\n+intent partial function. What used to be two cases is now one, and we\n+could add support for other methods like DELETE without adding any\n+complexity to its pattern matching. This is worth noting because\n+`ifDefined` is called on every intent at least once prior to its\n+evaluation. By making the intent more broadly defined, we\'ve reduced\n+the complexity of that and potentially improved runtime performance.\ndiff --git a/docs/08.markdown b/docs/06/b.markdown\nsimilarity index 100%\nrename from docs/08.markdown\nrename to docs/06/b.markdown\ndiff --git a/docs/09.markdown b/docs/06/c.markdown\nsimilarity index 100%\nrename from docs/09.markdown\nrename to docs/06/c.markdown\ndiff --git a/docs/07.markdown b/docs/07.markdown\nindex d309bae6..a9f62f19 100644\n--- a/docs/07.markdown\n+++ b/docs/07.markdown\n@@ -1,68 +1,90 @@\n-Request Matchers\n-----------------\n+Pattern Matching Pitfalls\n+-------------------------\n \n-### Methods and Paths\n+Java methods have a finite size, and the Scala compiler generates very\n+large methods for complex pattern matching. It can be surprisingly\n+easy to hit Java\'s limit and produce and exception in compilation. There\n+is [an open bug][1133] to address the problem in Scala.\n \n-Unfiltered supplies a wide range of *request matchers*—extractor\n-objects that work against requests—from path segments to HTTP methods\n-and headers. Applications use request matchers to define whether and\n-how they will respond to a request.\n+[1133]: https://lampsvn.epfl.ch/trac/scala/ticket/1133\n \n-    case GET(Path("/record/1")) => ...\n+There are several techniques for avoiding this limitation when writing\n+Unfiltered applications. One is to restructure matches so that common\n+cases are handled in one case, and differentiated in subsequent\n+matches. Instead of this:\n \n-This case will match GET requests to the path `/record/1`. To match\n-against path segments, we can nest one additional extractor:\n+    case ConditionA(Condition1(req)) => ...\n+    case ConditionA(Condition2(req)) => ...\n \n-    case GET(Path(Seg("record" :: id :: Nil))) => ...\n+You might write:\n \n-This matches any `id` string that is directly under the record\n-path. The `Seg` extractor object matches against the `String` type and\n-it is typically nested under a `Path` matcher. `Seg` extracts a lists\n-of strings from the supplied string, separated into path segments by\n-forward-slashes.\n-\n-### Reading Requests and Delayed Matching\n-\n-The above case clause matches a request to get a record. What about\n-putting them?\n+    case ConditionA(req) => req match {\n+      case Condition1(_) => ...\n+      case Condition2(_) => ...\n+      case _ => Pass\n+    }\n \n-    case req @ PUT(Path(Seg("record" :: id :: Nil))) =>\n-      val bytes = Body.bytes(req)\n-      ...\n+Another technique is to break up your cases into logical, named\n+groups. These can be combined into a single intent.\n \n-Access to the request body generally has side effects, such as the\n-consumption of a stream that can only be read once. For this reason\n-the body is not accessed from a request matcher, which could be\n-evaluated more than one time, but from utility functions that operate\n-on the request object.\n+    val foos = unfiltered.filter.Intent {\n+      case ConditionA(Condition1(req)) => ...\n+      case ConditionA(Condition2(req)) => ...\n+    }\n+    val bars = unfiltered.filter.Intent {\n+      case ConditionB(Condition1(req)) => ...\n+    }\n+    val fooBar = unfiltered.filter.Planify(foos.orElse(bars))\n \n-In this case, we assigned a reference to the request using `req @` and\n-then read its body into a byte array—on the assumption that its body\n-will fit into available memory. That aside, a minor annoyance is that\n-this code introduces some repetition in the matching expression.\n+For larger groupings of functionality, it may be useful to define\n+singleton objects holding logically divided intents.\n \n-    case GET(Path(Seg("record" :: id :: Nil))) => ...\n-    case req @ PUT(Path(Seg("record" :: id :: Nil))) => ...\n+    object Foos {\n+      import fun.stuff.into.scope._\n+      def intent = unfiltered.filter.Intent {\n+        case ConditionA(Condition1(req)) => ...\n+        case ConditionA(Condition2(req)) => ...\n+      }\n+    }\n+    object Bars {\n+      def intent = unfiltered.filter.Intent {\n+        case ConditionB(Condition1(req)) => ...\n+      }\n+    }\n+    object FooBar extends unfiltered.filter.Plan {\n+      def intent = Foos.intent.orElse(Bars.intent)\n+    }\n \n-An alternative is to match first on the path, then on the method:\n+You could also make use of separate plans, to be chained together by\n+the server.\n \n-    case req @ Path(Seg("record" :: id :: Nil)) => req match {\n-      case GET(_) => ...\n-      case PUT(_) => ...\n-      case _ => ...\n+    object Foos extends unfiltered.filter.Plan {\n+      import fun.stuff.into.scope._\n+      def intent = {\n+        case ConditionA(Condition1(req)) => ...\n+        case ConditionA(Condition2(req)) => ...\n+      }\n+    }\n+    object Bars extends unfiltered.filter.Plan {\n+      def intent = {\n+        case ConditionB(Condition1(req)) => ...\n+      }\n     }\n \n-This approach eliminates the duplicated code, but it\'s important to\n-recognize that it behaves differently as well. The original intent\n-partial function was simply *not defined* for request to that path\n-that were not a GET or a PUT. The latest one matches any request to\n-that path, and therefore it must return a value for all methods with\n-its match expression.\n+And lastly, if there is no logical way to divide up a partial function\n+that is large enough to cause a compilation error, you can always\n+split it arbitrarily with default cases:\n+\n+    def intent = {\n+      case ConditionA(Condition1(req)) => ...\n+      case ConditionA(Condition2(req)) => ...\n+      case req => req match => {\n+        case ConditionB(Condition1(req)) => ...\n+        case _ => Pass\n+      }\n+    }\n \n-Importantly, delaying the match on request method simplified the\n-intent partial function. What used to be two cases is now one, and we\n-could add support for other methods like DELETE without adding any\n-complexity to its pattern matching. This is worth noting because\n-`ifDefined` is called on every intent at least once prior to its\n-evaluation. By making the intent more broadly defined, we\'ve reduced\n-the complexity of that and potentially improved runtime performance.\n+Be aware that this last intent is *defined* for all requests. Because it\n+includes a top-level default case, its `orElse` method will never call\n+a partial function passed to it. The `Pass` object however will instruct\n+a plan to treat requests that fall to the end as non-matching.\ndiff --git a/docs/10.markdown b/docs/10.markdown\ndeleted file mode 100644\nindex a9f62f19..00000000\n--- a/docs/10.markdown\n+++ /dev/null\n@@ -1,90 +0,0 @@\n-Pattern Matching Pitfalls\n--------------------------\n-\n-Java methods have a finite size, and the Scala compiler generates very\n-large methods for complex pattern matching. It can be surprisingly\n-easy to hit Java\'s limit and produce and exception in compilation. There\n-is [an open bug][1133] to address the problem in Scala.\n-\n-[1133]: https://lampsvn.epfl.ch/trac/scala/ticket/1133\n-\n-There are several techniques for avoiding this limitation when writing\n-Unfiltered applications. One is to restructure matches so that common\n-cases are handled in one case, and differentiated in subsequent\n-matches. Instead of this:\n-\n-    case ConditionA(Condition1(req)) => ...\n-    case ConditionA(Condition2(req)) => ...\n-\n-You might write:\n-\n-    case ConditionA(req) => req match {\n-      case Condition1(_) => ...\n-      case Condition2(_) => ...\n-      case _ => Pass\n-    }\n-\n-Another technique is to break up your cases into logical, named\n-groups. These can be combined into a single intent.\n-\n-    val foos = unfiltered.filter.Intent {\n-      case ConditionA(Condition1(req)) => ...\n-      case ConditionA(Condition2(req)) => ...\n-    }\n-    val bars = unfiltered.filter.Intent {\n-      case ConditionB(Condition1(req)) => ...\n-    }\n-    val fooBar = unfiltered.filter.Planify(foos.orElse(bars))\n-\n-For larger groupings of functionality, it may be useful to define\n-singleton objects holding logically divided intents.\n-\n-    object Foos {\n-      import fun.stuff.into.scope._\n-      def intent = unfiltered.filter.Intent {\n-        case ConditionA(Condition1(req)) => ...\n-        case ConditionA(Condition2(req)) => ...\n-      }\n-    }\n-    object Bars {\n-      def intent = unfiltered.filter.Intent {\n-        case ConditionB(Condition1(req)) => ...\n-      }\n-    }\n-    object FooBar extends unfiltered.filter.Plan {\n-      def intent = Foos.intent.orElse(Bars.intent)\n-    }\n-\n-You could also make use of separate plans, to be chained together by\n-the server.\n-\n-    object Foos extends unfiltered.filter.Plan {\n-      import fun.stuff.into.scope._\n-      def intent = {\n-        case ConditionA(Condition1(req)) => ...\n-        case ConditionA(Condition2(req)) => ...\n-      }\n-    }\n-    object Bars extends unfiltered.filter.Plan {\n-      def intent = {\n-        case ConditionB(Condition1(req)) => ...\n-      }\n-    }\n-\n-And lastly, if there is no logical way to divide up a partial function\n-that is large enough to cause a compilation error, you can always\n-split it arbitrarily with default cases:\n-\n-    def intent = {\n-      case ConditionA(Condition1(req)) => ...\n-      case ConditionA(Condition2(req)) => ...\n-      case req => req match => {\n-        case ConditionB(Condition1(req)) => ...\n-        case _ => Pass\n-      }\n-    }\n-\n-Be aware that this last intent is *defined* for all requests. Because it\n-includes a top-level default case, its `orElse` method will never call\n-a partial function passed to it. The `Pass` object however will instruct\n-a plan to treat requests that fall to the end as non-matching.\n', 'commit_subject': 'shuffle', 'repo_name': 'unfiltered/unfiltered', 'committer': {'name': 'Nathan Hamblen', 'email': '2e8aa918660411855c6d44d5bb2da677aa033255@technically.us', 'time_sec': '1306098869', 'tz_offset': '-240', 'date': {'seconds': '1306098869'}}, 'commit_tree': 'ecb60eb24c72bbaae635f538e03e090b806a2c4b', 'commit_message': 'shuffle\n', 'language_name': 'JavaScript', 'license': 'mit', 'hunks': '@@ -0,0 +1,68 @@\n+Request Matchers\n+----------------\n+\n+### Methods and Paths\n+\n+Unfiltered supplies a wide range of *request matchers*—extractor\n+objects that work against requests—from path segments to HTTP methods\n+and headers. Applications use request matchers to define whether and\n+how they will respond to a request.\n+\n+    case GET(Path("/record/1")) => ...\n+\n+This case will match GET requests to the path `/record/1`. To match\n+against path segments, we can nest one additional extractor:\n+\n+    case GET(Path(Seg("record" :: id :: Nil))) => ...\n+\n+This matches any `id` string that is directly under the record\n+path. The `Seg` extractor object matches against the `String` type and\n+it is typically nested under a `Path` matcher. `Seg` extracts a lists\n+of strings from the supplied string, separated into path segments by\n+forward-slashes.\n+\n+### Reading Requests and Delayed Matching\n+\n+The above case clause matches a request to get a record. What about\n+putting them?\n+\n+    case req @ PUT(Path(Seg("record" :: id :: Nil))) =>\n+      val bytes = Body.bytes(req)\n+      ...\n+\n+Access to the request body generally has side effects, such as the\n+consumption of a stream that can only be read once. For this reason\n+the body is not accessed from a request matcher, which could be\n+evaluated more than one time, but from utility functions that operate\n+on the request object.\n+\n+In this case, we assigned a reference to the request using `req @` and\n+then read its body into a byte array—on the assumption that its body\n+will fit into available memory. That aside, a minor annoyance is that\n+this code introduces some repetition in the matching expression.\n+\n+    case GET(Path(Seg("record" :: id :: Nil))) => ...\n+    case req @ PUT(Path(Seg("record" :: id :: Nil))) => ...\n+\n+An alternative is to match first on the path, then on the method:\n+\n+    case req @ Path(Seg("record" :: id :: Nil)) => req match {\n+      case GET(_) => ...\n+      case PUT(_) => ...\n+      case _ => ...\n+    }\n+\n+This approach eliminates the duplicated code, but it\'s important to\n+recognize that it behaves differently as well. The original intent\n+partial function was simply *not defined* for request to that path\n+that were not a GET or a PUT. The latest one matches any request to\n+that path, and therefore it must return a value for all methods with\n+its match expression.\n+\n+Importantly, delaying the match on request method simplified the\n+intent partial function. What used to be two cases is now one, and we\n+could add support for other methods like DELETE without adding any\n+complexity to its pattern matching. This is worth noting because\n+`ifDefined` is called on every intent at least once prior to its\n+evaluation. By making the intent more broadly defined, we\'ve reduced\n+the complexity of that and potentially improved runtime performance.\n', 'addition_count': 68, 'deletion_count': 0, 'src_file': '/dev/null', 'tgt_file': 'b/docs/06/a.markdown', 'file_extension': '.markdown', 'before_file': 'ADDFILE', 'message': 'shuffle\n', 'author_name': 'Nathan Hamblen', 'lang': 'markdown'}