Fix bug in `readAsBytes` via http when content-length is set. (#24)
The `readAsBytes` method returns twice as much data as expected,
with the first half all zeroes. This comes from pre-allocating
the buffer, then appending to it (similar to issue 21, but with
`readAsBytes` instead of `readAsString`).
Updated the tests to also catch this case.
BUG: https://github.com/dart-lang/resource/issues/23
diff --git a/lib/src/io_io.dart b/lib/src/io_io.dart
index 0450651..03cc92e 100644
--- a/lib/src/io_io.dart
+++ b/lib/src/io_io.dart
@@ -4,13 +4,15 @@
import "dart:async" show Future, Stream;
import "dart:convert" show Encoding, LATIN1, UTF8;
-import "dart:io" show File,
- HttpStatus,
- HttpClient,
- HttpClientResponse,
- HttpClientRequest,
- HttpException,
- HttpHeaders;
+import "dart:io"
+ show
+ File,
+ HttpStatus,
+ HttpClient,
+ HttpClientResponse,
+ HttpClientRequest,
+ HttpException,
+ HttpHeaders;
import "package:typed_data/typed_buffers.dart" show Uint8Buffer;
@@ -43,7 +45,8 @@
_throwIfFailed(response, uri);
int length = response.contentLength;
if (length < 0) length = 0;
- var buffer = new Uint8Buffer(length);
+ // Create empty buffer with capacity matching contentLength.
+ var buffer = new Uint8Buffer(length)..length = 0;
await for (var bytes in response) {
buffer.addAll(bytes);
}
diff --git a/test/loader_http_test.dart b/test/loader_http_test.dart
index 155613e..f86e417 100644
--- a/test/loader_http_test.dart
+++ b/test/loader_http_test.dart
@@ -31,10 +31,12 @@
request.response.headers.contentType =
new ContentType("text", "plain", charset: encoding.name);
if (request.uri.query.contains("length")) {
- request.response.headers.contentLength = content.length;
+ request.response.headers.contentLength =
+ encoding.encode(content).length;
}
- request.response..write(content)
- ..close();
+ request.response
+ ..write(content)
+ ..close();
}).catchError(print);
});
@@ -53,26 +55,40 @@
test("Latin-1 encoding w/ length", () async {
// Regression test for issue #21.
var loader = ResourceLoader.defaultLoader;
- var newUri = uri.replace(query: "length"); // Request length set.
+ var newUri = uri.replace(query: "length"); // Request length set.
String string = await loader.readAsString(newUri, encoding: LATIN1);
expect(string, content);
});
test("UTF-8 encoding", () async {
var loader = ResourceLoader.defaultLoader;
+ var newUri = uri.replace(query: "length"); // Request length set.
+ String string = await loader.readAsString(newUri, encoding: UTF8);
+ expect(string, content);
+ });
+
+ test("UTF-8 encoding w/ length", () async {
+ var loader = ResourceLoader.defaultLoader;
String string = await loader.readAsString(uri, encoding: UTF8);
expect(string, content);
});
test("bytes", () async {
var loader = ResourceLoader.defaultLoader;
- List<int> bytes = await loader.readAsBytes(uri); // Sender uses Latin-1.
+ List<int> bytes = await loader.readAsBytes(uri); // Sender uses Latin-1.
+ expect(bytes, content.codeUnits);
+ });
+
+ test("bytes w/ length", () async {
+ var loader = ResourceLoader.defaultLoader;
+ var newUri = uri.replace(query: "length"); // Request length set.
+ List<int> bytes = await loader.readAsBytes(newUri); // Sender uses Latin-1.
expect(bytes, content.codeUnits);
});
test("byte stream", () async {
var loader = ResourceLoader.defaultLoader;
- var bytes = loader.openRead(uri); // Sender uses Latin-1.
+ var bytes = loader.openRead(uri); // Sender uses Latin-1.
var buffer = [];
await bytes.forEach(buffer.addAll);
expect(buffer, content.codeUnits);
@@ -80,20 +96,20 @@
test("not found - String", () async {
var loader = ResourceLoader.defaultLoader;
- var badUri = uri.resolve("file.not"); // .not makes server fail.
- expect(loader.readAsString(badUri), throws);
+ var badUri = uri.resolve("file.not"); // .not makes server fail.
+ expect(loader.readAsString(badUri), throwsException);
});
test("not found - bytes", () async {
var loader = ResourceLoader.defaultLoader;
- var badUri = uri.resolve("file.not"); // .not makes server fail.
- expect(loader.readAsBytes(badUri), throws);
+ var badUri = uri.resolve("file.not"); // .not makes server fail.
+ expect(loader.readAsBytes(badUri), throwsException);
});
test("not found - byte stream", () async {
var loader = ResourceLoader.defaultLoader;
- var badUri = uri.resolve("file.not"); // .not makes server fail.
- expect(loader.openRead(badUri).length, throws);
+ var badUri = uri.resolve("file.not"); // .not makes server fail.
+ expect(loader.openRead(badUri).length, throwsException);
});
tearDown(() {
@@ -102,7 +118,6 @@
});
}
-
Encoding parseAcceptCharset(List<String> headers) {
var encoding = LATIN1;
if (headers != null) {