Allow an empty url parameter in new Request().

This fits the stated semantics of the class, and should not have been
forbidden.

Closes #47

R=kevmoo@google.com

Review URL: https://codereview.chromium.org//1217503009.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee655d7..9754a56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,10 @@
-## 0.6.2
+## 0.6.1+3
 
 * Updated minimum SDK to `1.9.0`.
 
+* Allow an empty `url` parameter to be passed in to `new Request()`. This fits
+  the stated semantics of the class, and should not have been forbidden.
+
 ## 0.6.1+2
 
 * `logRequests` outputs a better message a request has a query string.
diff --git a/lib/src/request.dart b/lib/src/request.dart
index 85e4656..7e4f869 100644
--- a/lib/src/request.dart
+++ b/lib/src/request.dart
@@ -298,7 +298,8 @@
     }
 
     var startOfUrl = requestedUri.path.length - url.path.length;
-    if (requestedUri.path.substring(startOfUrl - 1, startOfUrl) != '/') {
+    if (url.path.isNotEmpty &&
+        requestedUri.path.substring(startOfUrl - 1, startOfUrl) != '/') {
       throw new ArgumentError('url "$url" must be on a path boundary in '
           'requestedUri "$requestedUri".');
     }
@@ -339,6 +340,8 @@
 
     return handlerPath;
   } else if (url != null) {
+    if (url.path.isEmpty) return requestedUri.path;
+
     var index = requestedUri.path.indexOf(url.path);
     return requestedUri.path.substring(0, index);
   } else {
diff --git a/pubspec.yaml b/pubspec.yaml
index eb158fd..26515fa 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: shelf
-version: 0.6.2-dev
+version: 0.6.1+3
 author: Dart Team <misc@dartlang.org>
 description: Web Server Middleware for Dart
 homepage: https://github.com/dart-lang/shelf
diff --git a/test/request_test.dart b/test/request_test.dart
index e953954..b02de54 100644
--- a/test/request_test.dart
+++ b/test/request_test.dart
@@ -49,6 +49,13 @@
             url: Uri.parse("bar?q=1"));
         expect(request.url, equals(Uri.parse("bar?q=1")));
       });
+
+      test("may be empty", () {
+        var request = new Request(
+            'GET', Uri.parse("http://localhost/foo/bar"),
+            url: Uri.parse(""));
+        expect(request.url, equals(Uri.parse("")));
+      });
     });
 
     group("handlerPath", () {
@@ -78,6 +85,14 @@
         expect(request.handlerPath, equals("/foo/"));
         expect(request.url, equals(Uri.parse("bar?q=1")));
       });
+
+      test("may be a single slash", () {
+        var request = new Request(
+            'GET', Uri.parse("http://localhost/foo/bar?q=1"),
+            handlerPath: '/');
+        expect(request.handlerPath, equals("/"));
+        expect(request.url, equals(Uri.parse("foo/bar?q=1")));
+      });
     });
 
     group("errors", () {
@@ -151,6 +166,14 @@
                 handlerPath: 'test');
           }, throwsArgumentError);
         });
+
+        test('must be the requestedUri path if url is empty', () {
+          expect(() {
+            new Request('GET', Uri.parse('http://localhost/test'),
+                handlerPath: '/',
+                url: Uri.parse(''));
+          }, throwsArgumentError);
+        });
       });
 
       group('handlerPath + url must', () {