Index: pkg/http_server/lib/src/virtual_directory.dart |
diff --git a/pkg/http_server/lib/src/virtual_directory.dart b/pkg/http_server/lib/src/virtual_directory.dart |
index 6dfec5d9124d7644a9e4479edcf331e0833a7754..7ed4db80edebcc3ae5d01207161c3a44ed7a619d 100644 |
--- a/pkg/http_server/lib/src/virtual_directory.dart |
+++ b/pkg/http_server/lib/src/virtual_directory.dart |
@@ -211,44 +211,58 @@ class VirtualDirectory { |
if (request.method == 'HEAD') { |
response.close(); |
kustermann
2014/11/14 13:25:26
Maybe set the content-length header in case of HEA
Søren Gjesse
2014/11/14 15:27:29
Yes, done. Also added it for serving the whole fil
|
- return null; |
+ return; |
} |
return file.length().then((length) { |
- String range = request.headers.value("range"); |
+ String range = request.headers.value(HttpHeaders.RANGE); |
if (range != null) { |
Anders Johnsen
2014/11/13 16:12:31
This range handling is getting quite complicated.
Søren Gjesse
2014/11/14 15:27:29
I will postpone this to a separate CL, as I will a
|
// We only support one range, where the standard support several. |
Match matches = new RegExp(r"^bytes=(\d*)\-(\d*)$").firstMatch(range); |
// If the range header have the right format, handle it. |
- if (matches != null) { |
+ if (matches != null && |
+ (matches[1].isNotEmpty || matches[2].isNotEmpty)) { |
// Serve sub-range. |
- int start; |
- int end; |
+ int start; // First byte position - inclusive. |
+ int end; // Last byte position - inclusive. |
if (matches[1].isEmpty) { |
- start = matches[2].isEmpty ? |
- length : |
- length - int.parse(matches[2]); |
- end = length; |
+ start = length - int.parse(matches[2]); |
+ if (start < 0) start = 0; |
+ end = length - 1; |
} else { |
start = int.parse(matches[1]); |
- end = matches[2].isEmpty ? length : int.parse(matches[2]) + 1; |
+ end = matches[2].isEmpty ? length - 1: int.parse(matches[2]); |
} |
+ // If the range is syntactically invalid the Range header |
+ // MUST be ignored (RFC 2616 section 14.35.1). |
+ if (start <= end) { |
+ if (end > length) { |
kustermann
2014/11/14 13:25:26
Since end is inclusive, shouldn't this be "end >=
Søren Gjesse
2014/11/14 15:27:29
Yes. Good catch. Added additional test.
|
+ end = length - 1; |
+ } |
- // Override Content-Length with the actual bytes sent. |
- response.headers.set(HttpHeaders.CONTENT_LENGTH, end - start); |
- |
- // Set 'Partial Content' status code. |
- response.statusCode = HttpStatus.PARTIAL_CONTENT; |
- response.headers.set(HttpHeaders.CONTENT_RANGE, |
- "bytes $start-${end - 1}/$length"); |
+ if (start >= length) { |
+ response.statusCode = |
+ HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE; |
+ response.close(); |
+ return; |
kustermann
2014/11/14 13:25:27
Maybe use cascades:
response
..statusCode =
Søren Gjesse
2014/11/14 15:27:29
Done.
|
+ } |
- // Pipe the 'range' of the file. |
- file.openRead(start, end) |
- .pipe(new _VirtualDirectoryFileStream(response, file.path)) |
- .catchError((_) { |
- // TODO(kevmoo): log errors |
- }); |
- return; |
+ // Override Content-Length with the actual bytes sent. |
+ response.headers.set(HttpHeaders.CONTENT_LENGTH, end - start + 1); |
+ |
+ // Set 'Partial Content' status code. |
+ response.statusCode = HttpStatus.PARTIAL_CONTENT; |
+ response.headers.set(HttpHeaders.CONTENT_RANGE, |
+ "bytes $start-$end/$length"); |
kustermann
2014/11/14 13:25:27
Cascades?
Søren Gjesse
2014/11/14 15:27:29
Done.
|
+ |
+ // Pipe the 'range' of the file. |
+ file.openRead(start, end + 1) |
+ .pipe(new _VirtualDirectoryFileStream(response, file.path)) |
+ .catchError((_) { |
+ // TODO(kevmoo): log errors |
+ }); |
+ return; |
+ } |
} |
} |