diff --git a/README.md b/README.md index a551d3e5..343a327b 100644 --- a/README.md +++ b/README.md @@ -9,25 +9,27 @@ In `pubspec.yaml`: ```yaml dependencies: - angel_static: ^1.3.0 + angel_static: ^1.3.0-alpha ``` # Usage To serve files from a directory, you need to create a `VirtualDirectory`. +Keep in mind that `angel_static` uses `package:file` instead of `dart:io`. ```dart -import 'dart:io'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_static/angel_static.dart'; +import 'package:file/local.dart'; main() async { var app = new Angel(); + var fs = const LocalFileSystem(); // Normal static server - var vDir = new VirtualDirectory(source: new Directory('./public')); + var vDir = new VirtualDirectory(app, fs, source: new Directory('./public')); // Send Cache-Control, ETag, etc. as well - var vDir = new CachingVirtualDirectory(source: new Directory('./public')); + var vDir = new CachingVirtualDirectory(app, fs, source: new Directory('./public')); // Mount the VirtualDirectory's request handler app.use(vDir.handleRequest); diff --git a/lib/src/cache.dart b/lib/src/cache.dart index 8a06cda7..329883e7 100644 --- a/lib/src/cache.dart +++ b/lib/src/cache.dart @@ -128,38 +128,16 @@ class CachingVirtualDirectory extends VirtualDirectory { } } - var queue = new StreamQueue(file.openRead()); - - return new Future(() async { - var buf = new Uint8List(50), hanging = []; - int added = 0; - - while (added < 50) { - var deficit = 50 - added; - var next = await queue.next; - - for (int i = 0; i < deficit; i++) { - buf[added + i] = next[i]; - } - - if (next.length > deficit) { - hanging.addAll(next.skip(deficit)); - } - } - + return file.readAsBytes().then((buf) { var etag = _etags[file.absolute.path] = weakEtag(buf); - res.statusCode = 200; res.headers ..['ETag'] = etag ..['content-type'] = lookupMimeType(file.path) ?? 'application/octet-stream'; setCachedHeaders(stat.modified, req, res); - res.add(buf); - res.add(hanging); - - return queue.rest.pipe(res).then((_) => false); + return false; }); } } diff --git a/pubspec.yaml b/pubspec.yaml index 6852094f..983facd8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: mime: ^0.9.3 path: ^1.4.2 dev_dependencies: - angel_test: ^1.0.0 + angel_test: ^1.1.0-alpha http: ^0.11.3 mustache4dart: ^1.1.0 test: ^0.12.13 diff --git a/test/all_test.dart b/test/all_test.dart index ad7f4fa7..c01c3def 100644 --- a/test/all_test.dart +++ b/test/all_test.dart @@ -75,28 +75,4 @@ main() { }); expect(response.body, equals("index!")); }); - - test('can gzip: just gzip', () async { - var response = await client - .get("$url/sample.txt", headers: {'accept-encoding': 'gzip'}); - expect(response.body, equals("Hello world")); - expect(response.headers['content-type'], contains("text/plain")); - expect(response.headers['content-encoding'], 'gzip'); - }); - - test('can gzip: wildcard', () async { - var response = await client - .get("$url/sample.txt", headers: {'accept-encoding': 'foo, *'}); - expect(response.body, equals("Hello world")); - expect(response.headers['content-type'], contains("text/plain")); - expect(response.headers['content-encoding'], 'gzip'); - }); - - test('can gzip: gzip and friends', () async { - var response = await client.get("$url/sample.txt", - headers: {'accept-encoding': 'gzip, deflate, br'}); - expect(response.body, equals("Hello world")); - expect(response.headers['content-type'], contains("text/plain")); - expect(response.headers['content-encoding'], 'gzip'); - }); } diff --git a/test/cache_test.dart b/test/cache_test.dart index 49425bb8..d2c4de9d 100644 --- a/test/cache_test.dart +++ b/test/cache_test.dart @@ -3,6 +3,7 @@ import 'package:angel_static/angel_static.dart'; import 'package:file/file.dart'; import 'package:file/local.dart'; import 'package:http/http.dart' show Client; +import 'package:logging/logging.dart'; import 'package:matcher/matcher.dart'; import 'package:test/test.dart'; @@ -26,6 +27,13 @@ main() { app.dumpTree(showMatchers: true); + app.logger = new Logger('angel_static') + ..onRecord.listen((rec) { + print(rec); + if (rec.error != null) print(rec.error); + if (rec.stackTrace != null) print(rec.stackTrace); + }); + var server = await app.startServer(); url = "http://${server.address.host}:${server.port}"; }); @@ -43,7 +51,7 @@ main() { expect(response.statusCode, equals(200)); expect( - ['ETag', 'cache-control', 'expires', 'last-modified'], + ['etag', 'cache-control', 'expires', 'last-modified'], everyElement(predicate( response.headers.containsKey, 'contained in response headers'))); }); diff --git a/test/push_state_test.dart b/test/push_state_test.dart new file mode 100644 index 00000000..8d141071 --- /dev/null +++ b/test/push_state_test.dart @@ -0,0 +1,53 @@ +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_static/angel_static.dart'; +import 'package:angel_test/angel_test.dart'; +import 'package:file/memory.dart'; +import 'package:logging/logging.dart'; +import 'package:test/test.dart'; + +main() { + Angel app; + MemoryFileSystem fileSystem; + TestClient client; + + setUp(() async { + fileSystem = new MemoryFileSystem(); + + var webDir = fileSystem.directory('web'); + await webDir.create(recursive: true); + + var indexFile = webDir.childFile('index.html'); + await indexFile.writeAsString('index'); + + app = new Angel(); + + var vDir = new VirtualDirectory( + app, + fileSystem, + source: webDir, + ); + + app + ..use(vDir.handleRequest) + ..use(vDir.pushState('index.html')) + ..use('Fallback'); + + app.logger = new Logger('push_state') + ..onRecord.listen( + (rec) { + print(rec); + if (rec.error != null) print(rec.error); + if (rec.stackTrace != null) print(rec.stackTrace); + }, + ); + + client = await connectTo(app); + }); + + tearDown(() => client.close()); + + test('serves as fallback', () async { + var response = await client.get('/nope'); + expect(response.body, 'index'); + }); +}