Fix handlerPath check when a path contains // (#146)
If the requested URI is not canonical and contains a `//` separator the
previous check would not allow changing a request to set the
`handlerPath` to the part of the path leading up to the `//`. This shows
up in some requests used in tests for the VM service.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 571f425..ad56d5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.7.9
+
+* Allow a `handlerPath` to lead up to a double `//` in a URI.
+
## 0.7.8
* Handle malformed URLs (400 instead of 500).
diff --git a/lib/src/request.dart b/lib/src/request.dart
index e3f94a6..624e7cb 100644
--- a/lib/src/request.dart
+++ b/lib/src/request.dart
@@ -191,8 +191,10 @@
// cannot actually combine this.handlerPath and this.url.path, but we can
// compare the pathSegments. In practice exposing this.url.path as a Uri
// and not a String is probably the underlying flaw here.
- final pathSegments = Uri(path: this.handlerPath).pathSegments.join('/') +
- this.url.pathSegments.join('/');
+ final handlerPart = Uri(path: this.handlerPath).pathSegments.join('/');
+ final rest = this.url.pathSegments.join('/');
+ final join = this.url.path.startsWith('/') ? '/' : '';
+ final pathSegments = '$handlerPart$join$rest';
if (pathSegments != requestedUri.pathSegments.join('/')) {
throw ArgumentError.value(
requestedUri,
diff --git a/pubspec.yaml b/pubspec.yaml
index b71d38d..938b3a4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: shelf
-version: 0.7.8
+version: 0.7.9
description: >-
A model for web server middleware that encourages composition and easy reuse
homepage: https://github.com/dart-lang/shelf
diff --git a/test/request_test.dart b/test/request_test.dart
index 8aaac86..138a6ef 100644
--- a/test/request_test.dart
+++ b/test/request_test.dart
@@ -365,6 +365,16 @@
expect(copy.url, Uri.parse(''));
});
+ test('allows changing path leading to double //', () {
+ var uri = Uri.parse('https://test.example.com/some_base//more');
+ var request = Request('GET', uri,
+ handlerPath: '', url: Uri.parse('some_base//more'));
+
+ var copy = request.change(path: 'some_base');
+ expect(copy.handlerPath, '/some_base/');
+ expect(copy.url, Uri.parse('/more'));
+ });
+
test('throws if path does not match existing uri', () {
var uri = Uri.parse('https://test.example.com/static/dir/file.html');
var request = Request('GET', uri,