Some cleanup
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7b9d5d..53c712c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.2.4
+
+* Add support for "sniffing" the content of the file for the content-type via an optional
+ `useHeaderBytesForContentType` argument on `createStaticHandler`.
+
## 0.2.3+4
* Support `http_parser` 3.0.0.
diff --git a/lib/src/static_handler.dart b/lib/src/static_handler.dart
index 725c438..a2a1b5c 100644
--- a/lib/src/static_handler.dart
+++ b/lib/src/static_handler.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
+import 'dart:math' as math;
+import 'package:convert/convert.dart';
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart' as mime;
import 'package:path/path.dart' as p;
@@ -28,13 +30,13 @@
/// If no [defaultDocument] is found and [listDirectories] is true, then the
/// handler produces a listing of the directory.
///
-/// If [useHeaderBytesForContentType] is set to false, then the content type will
-/// be determined by the file's extension, as is the mime library's default behavior.
-/// Setting it to true will cause up tot he first 25 bytes of the file to be read
-/// and used to determine the content type.
+/// If [useHeaderBytesForContentType] is `true`, the contents of the
+/// file will be used along with the file path to determine the content type.
Handler createStaticHandler(String fileSystemPath,
- {bool serveFilesOutsidePath: false, String defaultDocument,
- bool listDirectories: false, bool useHeaderBytesForContentType: false}) {
+ {bool serveFilesOutsidePath: false,
+ String defaultDocument,
+ bool listDirectories: false,
+ bool useHeaderBytesForContentType: false}) {
var rootDir = new Directory(fileSystemPath);
if (!rootDir.existsSync()) {
throw new ArgumentError('A directory corresponding to fileSystemPath '
@@ -105,15 +107,16 @@
HttpHeaders.LAST_MODIFIED: formatHttpDate(fileStat.changed)
};
+ String contentType;
+ if (useHeaderBytesForContentType) {
+ var length =
+ math.min(mime.defaultMagicNumbersMaxLength, file.lengthSync());
- var contentType;
- if(useHeaderBytesForContentType) {
- int length = 25; // The longest file header identifier
- int file_length =file.lengthSync();
- if(file_length<length)
- length = file_length;
- List<int> magicBytes = await file.openRead(0,length).single;
- contentType = mime.lookupMimeType(file.path, headerBytes: magicBytes);
+ var byteSink = new ByteAccumulatorSink();
+
+ await file.openRead(0, length).listen(byteSink.add).asFuture();
+
+ contentType = mime.lookupMimeType(file.path, headerBytes: byteSink.bytes);
} else {
contentType = mime.lookupMimeType(file.path);
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 6396da8..f1cc8d4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,12 @@
name: shelf_static
-version: 0.2.3+4
+version: 0.2.4
author: Dart Team <misc@dartlang.org>
description: Static file server support for Shelf
homepage: https://github.com/dart-lang/shelf_static
environment:
sdk: '>=1.7.0 <2.0.0'
dependencies:
+ convert: '>=1.0.0 <3.0.0'
http_parser: '>=0.0.2+2 <4.0.0'
mime: '>=0.9.0 <0.10.0'
path: '>=1.1.0 <2.0.0'
diff --git a/test/basic_file_test.dart b/test/basic_file_test.dart
index 3de28f1..8348761 100644
--- a/test/basic_file_test.dart
+++ b/test/basic_file_test.dart
@@ -25,13 +25,20 @@
d.file('index.html', '<html></html>').create();
d.file('root.txt', 'root txt').create();
d.file('random.unknown', 'no clue').create();
- d.binaryFile('header_bytes_test_image', BASE64.decode(r"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AYRETkSXaxBzQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAbUlEQVQI1wXBvwpBYRwA0HO/kjBKJmXRLWXxJ4PsnsMTeAEPILvNZrybF7B4A6XvQW6k+DkHwqgM1TnMpoEoDMtwOJE7pB/VXmF3CdseucmjxaAruR41Pl9p/Gbyoq5B9FeL2OR7zJ+3aC/X8QdQCyIArPsHkQAAAABJRU5ErkJggg==")).create();
- d
- .dir('files', [
+
+ var pngBytesContent =
+ r"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABmJLR0QA/wD/AP+gvae"
+ r"TAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AYRETkSXaxBzQAAAB1pVFh0Q2"
+ r"9tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAbUlEQVQI1wXBvwpBYRwA0"
+ r"HO/kjBKJmXRLWXxJ4PsnsMTeAEPILvNZrybF7B4A6XvQW6k+DkHwqgM1TnMpoEoDMtw"
+ r"OJE7pB/VXmF3CdseucmjxaAruR41Pl9p/Gbyoq5B9FeL2OR7zJ+3aC/X8QdQCyIArPs"
+ r"HkQAAAABJRU5ErkJggg==";
+
+ d.dir('files', [
d.file('test.txt', 'test txt content'),
- d.file('with space.txt', 'with space content')
- ])
- .create();
+ d.file('with space.txt', 'with space content'),
+ d.binaryFile('header_bytes_test_image', BASE64.decode(pngBytesContent))
+ ]).create();
currentSchedule.onComplete.schedule(() {
d.defaultRoot = null;
@@ -202,9 +209,11 @@
test('magic_bytes_test_image should be image/png', () {
schedule(() {
- var handler = createStaticHandler(d.defaultRoot, useHeaderBytesForContentType: true);
+ var handler = createStaticHandler(d.defaultRoot,
+ useHeaderBytesForContentType: true);
- return makeRequest(handler, '/header_bytes_test_image').then((response) {
+ return makeRequest(handler, '/files/header_bytes_test_image')
+ .then((response) {
expect(response.mimeType, "image/png");
});
});