Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1027)

Unified Diff: pkg/http_server/lib/src/virtual_directory.dart

Issue 721213002: Fix a number of issues with the Range header handling for serving files (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/http_server/CHANGELOG.md ('k') | pkg/http_server/pubspec.yaml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..d82fd992c6e30e6bc287f83b15920e3a49e3646e 100644
--- a/pkg/http_server/lib/src/virtual_directory.dart
+++ b/pkg/http_server/lib/src/virtual_directory.dart
@@ -209,54 +209,73 @@ class VirtualDirectory {
response.headers.set(HttpHeaders.LAST_MODIFIED, lastModified);
response.headers.set(HttpHeaders.ACCEPT_RANGES, "bytes");
- if (request.method == 'HEAD') {
- response.close();
- return null;
- }
-
return file.length().then((length) {
- String range = request.headers.value("range");
+ String range = request.headers.value(HttpHeaders.RANGE);
if (range != null) {
// 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) {
+ end = length - 1;
+ }
- // Override Content-Length with the actual bytes sent.
- response.headers.set(HttpHeaders.CONTENT_LENGTH, end - start);
+ if (start >= length) {
+ response
+ ..statusCode = HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE
+ ..close();
+ return;
+ }
- // Set 'Partial Content' status code.
- response.statusCode = HttpStatus.PARTIAL_CONTENT;
- response.headers.set(HttpHeaders.CONTENT_RANGE,
- "bytes $start-${end - 1}/$length");
+ // Override Content-Length with the actual bytes sent.
+ response.headers.set(HttpHeaders.CONTENT_LENGTH, end - start + 1);
- // Pipe the 'range' of the file.
- file.openRead(start, end)
- .pipe(new _VirtualDirectoryFileStream(response, file.path))
- .catchError((_) {
- // TODO(kevmoo): log errors
- });
- return;
+ // Set 'Partial Content' status code.
+ response
+ ..statusCode = HttpStatus.PARTIAL_CONTENT
+ ..headers.set(HttpHeaders.CONTENT_RANGE,
+ 'bytes $start-$end/$length');
+
+ // Pipe the 'range' of the file.
+ if (request.method == 'HEAD') {
+ response.close();
+ } else {
+ file.openRead(start, end + 1)
+ .pipe(new _VirtualDirectoryFileStream(response, file.path))
+ .catchError((_) {
+ // TODO(kevmoo): log errors
+ });
+ }
+ return;
+ }
}
}
- file.openRead()
- .pipe(new _VirtualDirectoryFileStream(response, file.path))
- .catchError((_) {
- // TODO(kevmoo): log errors
- });
+ response.headers.set(HttpHeaders.CONTENT_LENGTH, length);
+ if (request.method == 'HEAD') {
+ response.close();
+ } else {
+ file.openRead()
+ .pipe(new _VirtualDirectoryFileStream(response, file.path))
+ .catchError((_) {
+ // TODO(kevmoo): log errors
+ });
+ }
});
}).catchError((_) {
response.statusCode = HttpStatus.NOT_FOUND;
« no previous file with comments | « pkg/http_server/CHANGELOG.md ('k') | pkg/http_server/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698