Handle malformed URLs (400 instead of 500). (#144)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a62e70..571f425 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.7.8
+
+* Handle malformed URLs (400 instead of 500).
+
## 0.7.7
* Fix internal error in `Request` when `.change()` matches the full path.
diff --git a/lib/src/request.dart b/lib/src/request.dart
index d1740c3..e3f94a6 100644
--- a/lib/src/request.dart
+++ b/lib/src/request.dart
@@ -149,7 +149,7 @@
/// Any [Request] created by calling [change] will pass [_onHijack] from the
/// source [Request] to ensure that [hijack] can only be called once, even
/// from a changed [Request].
- Request._(this.method, Uri requestedUri,
+ Request._(this.method, this.requestedUri,
{String protocolVersion,
Map<String, /* String | List<String> */ Object> headers,
String handlerPath,
@@ -158,8 +158,7 @@
Encoding encoding,
Map<String, Object> context,
_OnHijack onHijack})
- : requestedUri = requestedUri,
- protocolVersion = protocolVersion ?? '1.1',
+ : protocolVersion = protocolVersion ?? '1.1',
url = _computeUrl(requestedUri, handlerPath, url),
handlerPath = _computeHandlerPath(requestedUri, handlerPath, url),
_onHijack = onHijack,
@@ -168,6 +167,16 @@
throw ArgumentError.value(method, 'method', 'cannot be empty.');
}
+ try {
+ // Trigger URI parsing methods that may throw format exception (in Request
+ // constructor or in handlers / routing).
+ requestedUri.pathSegments;
+ requestedUri.queryParametersAll;
+ } on FormatException catch (e) {
+ throw ArgumentError.value(
+ requestedUri, 'requestedUri', 'URI parsing failed: $e');
+ }
+
if (!requestedUri.isAbsolute) {
throw ArgumentError.value(
requestedUri, 'requestedUri', 'must be an absolute URL.');
@@ -184,7 +193,7 @@
// and not a String is probably the underlying flaw here.
final pathSegments = Uri(path: this.handlerPath).pathSegments.join('/') +
this.url.pathSegments.join('/');
- if (pathSegments != this.requestedUri.pathSegments.join('/')) {
+ if (pathSegments != requestedUri.pathSegments.join('/')) {
throw ArgumentError.value(
requestedUri,
'requestedUri',
diff --git a/pubspec.yaml b/pubspec.yaml
index 12eaa7a..b71d38d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: shelf
-version: 0.7.7
+version: 0.7.8
description: >-
A model for web server middleware that encourages composition and easy reuse
homepage: https://github.com/dart-lang/shelf
diff --git a/test/io_server_test.dart b/test/io_server_test.dart
index 26226d4..4ab6a2a 100644
--- a/test/io_server_test.dart
+++ b/test/io_server_test.dart
@@ -31,6 +31,14 @@
expect(await http.read(server.url), equals('Hello from /'));
});
+ test('Handles malformed requests gracefully.', () async {
+ server.mount(syncHandler);
+ final rs =
+ await http.get('${server.url}/%D0%C2%BD%A8%CE%C4%BC%FE%BC%D0.zip');
+ expect(rs.statusCode, 400);
+ expect(rs.body, 'Bad Request');
+ });
+
test('delays HTTP requests until a handler is mounted', () async {
expect(http.read(server.url), completion(equals('Hello from /')));
await Future.delayed(Duration.zero);