Dart 2 fixes + bump version + allow buffering

This commit is contained in:
Tobe O 2018-07-09 13:38:22 -04:00
parent 6945c538c3
commit cceabd3c7d
9 changed files with 51 additions and 26 deletions

View file

@ -1,3 +1,7 @@
# 1.3.0+1
* Dart 2 fixes.
* Enable optionally writing responses to the buffer instead of streaming.
# 1.3.0 # 1.3.0
* `pushState` uses `strict` mode when `accepts` is passed. * `pushState` uses `strict` mode when `accepts` is passed.

View file

@ -1,2 +1,3 @@
analyzer: analyzer:
strong-mode: true strong-mode:
implicit-casts: false

View file

@ -4,6 +4,7 @@ import 'package:file/local.dart';
main() async { main() async {
var app = new Angel(); var app = new Angel();
var http = new AngelHttp(app);
var fs = const LocalFileSystem(); var fs = const LocalFileSystem();
var vDir = new VirtualDirectory( var vDir = new VirtualDirectory(
app, app,
@ -13,6 +14,6 @@ main() async {
); );
app.use(vDir.handleRequest); app.use(vDir.handleRequest);
var server = await app.startServer('127.0.0.1', 3000); var server = await http.startServer('127.0.0.1', 3000);
print('Listening at http://${server.address.address}:${server.port}'); print('Listening at http://${server.address.address}:${server.port}');
} }

View file

@ -1,8 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';
import 'package:async/async.dart'; import 'package:dart2_constant/convert.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:mime/mime.dart'; import 'package:mime/mime.dart';
@ -15,7 +13,7 @@ String formatDateForHttp(DateTime dt) => _fmt.format(dt.toUtc()) + ' GMT';
/// Generates a weak ETag from the given buffer. /// Generates a weak ETag from the given buffer.
String weakEtag(List<int> buf) { String weakEtag(List<int> buf) {
return 'W/${buf.length}' + BASE64URL.encode(buf.take(50).toList()); return 'W/${buf.length}' + base64Url.encode(buf.take(50).toList());
} }
/// Returns a string representation of the given [CacheAccessLevel]. /// Returns a string representation of the given [CacheAccessLevel].
@ -61,6 +59,7 @@ class CachingVirtualDirectory extends VirtualDirectory {
this.onlyInProduction: false, this.onlyInProduction: false,
this.useEtags: true, this.useEtags: true,
bool allowDirectoryListing, bool allowDirectoryListing,
bool useStream,
String publicPath, String publicPath,
callback(File file, RequestContext req, ResponseContext res)}) callback(File file, RequestContext req, ResponseContext res)})
: super(app, fileSystem, : super(app, fileSystem,
@ -68,7 +67,8 @@ class CachingVirtualDirectory extends VirtualDirectory {
indexFileNames: indexFileNames ?? ['index.html'], indexFileNames: indexFileNames ?? ['index.html'],
publicPath: publicPath ?? '/', publicPath: publicPath ?? '/',
callback: callback, callback: callback,
allowDirectoryListing: allowDirectoryListing); allowDirectoryListing: allowDirectoryListing,
useStream: useStream);
@override @override
Future<bool> serveFile( Future<bool> serveFile(

View file

@ -46,12 +46,18 @@ class VirtualDirectory {
/// If `true` (default: `false`), then if a directory does not contain any of the specific [indexFileNames], a default directory listing will be served. /// If `true` (default: `false`), then if a directory does not contain any of the specific [indexFileNames], a default directory listing will be served.
final bool allowDirectoryListing; final bool allowDirectoryListing;
/// If `true` (default: `true`), then files will be opened as streams and piped into the request.
///
/// If not, the response buffer will be used instead.
final bool useStream;
VirtualDirectory(this.app, this.fileSystem, VirtualDirectory(this.app, this.fileSystem,
{Directory source, {Directory source,
this.indexFileNames: const ['index.html'], this.indexFileNames: const ['index.html'],
this.publicPath: '/', this.publicPath: '/',
this.callback, this.callback,
this.allowDirectoryListing: false}) { this.allowDirectoryListing: false,
this.useStream: true}) {
_prefix = publicPath.replaceAll(_straySlashes, ''); _prefix = publicPath.replaceAll(_straySlashes, '');
if (source != null) { if (source != null) {
_source = source; _source = source;
@ -86,7 +92,8 @@ class VirtualDirectory {
if (path == vPath) return new Future<bool>.value(true); if (path == vPath) return new Future<bool>.value(true);
if (accepts?.isNotEmpty == true) { if (accepts?.isNotEmpty == true) {
if (!accepts.any((x) => req.accepts(x, strict: true))) return new Future<bool>.value(true); if (!accepts.any((x) => req.accepts(x, strict: true)))
return new Future<bool>.value(true);
} }
return servePath(vPath, req, res); return servePath(vPath, req, res);
@ -111,8 +118,8 @@ class VirtualDirectory {
} }
/// Writes the file at the path given by the [stat] to a response. /// Writes the file at the path given by the [stat] to a response.
Future<bool> serveStat(String absolute, String relative, FileStat stat, RequestContext req, Future<bool> serveStat(String absolute, String relative, FileStat stat,
ResponseContext res) async { RequestContext req, ResponseContext res) async {
if (stat.type == FileSystemEntityType.DIRECTORY) if (stat.type == FileSystemEntityType.DIRECTORY)
return await serveDirectory( return await serveDirectory(
fileSystem.directory(absolute), relative, stat, req, res); fileSystem.directory(absolute), relative, stat, req, res);
@ -126,8 +133,8 @@ class VirtualDirectory {
} }
/// Serves the index file of a [directory], if it exists. /// Serves the index file of a [directory], if it exists.
Future<bool> serveDirectory(Directory directory, String relative, FileStat stat, Future<bool> serveDirectory(Directory directory, String relative,
RequestContext req, ResponseContext res) async { FileStat stat, RequestContext req, ResponseContext res) async {
for (String indexFileName in indexFileNames) { for (String indexFileName in indexFileNames) {
final index = final index =
fileSystem.file(directory.absolute.uri.resolve(indexFileName)); fileSystem.file(directory.absolute.uri.resolve(indexFileName));
@ -177,11 +184,9 @@ class VirtualDirectory {
type = '[Directory]'; type = '[Directory]';
else if (entity is Link) type = '[Link]'; else if (entity is Link) type = '[Link]';
if (relative.isNotEmpty) if (relative.isNotEmpty) href = '/' + relative + '/' + stub;
href = '/' + relative + '/' + stub;
if (entity is Directory) if (entity is Directory) href += '/';
href += '/';
res.write('<li><a href="$href">$type $stub</a></li>'); res.write('<li><a href="$href">$type $stub</a></li>');
} }
@ -215,14 +220,20 @@ class VirtualDirectory {
if (callback != null) { if (callback != null) {
var r = callback(file, req, res); var r = callback(file, req, res);
r = r is Future ? await r : r; r = r is Future ? await r : r;
if (r != null && r != true) return r; return r == true;
//if (r != null && r != true) return r;
} }
var type = lookupMimeType(file.path) ?? 'application/octet-stream'; var type = lookupMimeType(file.path) ?? 'application/octet-stream';
_ensureContentTypeAllowed(type, req); _ensureContentTypeAllowed(type, req);
res.headers['content-type'] = type; res.headers['content-type'] = type;
await file.openRead().pipe(res); if (useStream != true) {
res.buffer.add(await file.readAsBytes());
} else {
await file.openRead().pipe(res);
}
return false; return false;
} }
} }

View file

@ -1,12 +1,13 @@
name: angel_static name: angel_static
description: Static server middleware for Angel. description: Static server middleware for Angel.
environment: environment:
sdk: ">=1.19.0" sdk: ">=1.8.0 <3.0.0"
homepage: https://github.com/angel-dart/static homepage: https://github.com/angel-dart/static
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
version: 1.3.0 version: 1.3.0+1
dependencies: dependencies:
angel_framework: ^1.1.0-alpha angel_framework: ^1.1.0-alpha
dart2_constant: ^1.0.0
file: ^2.0.0 file: ^2.0.0
intl: ">=0.0.0 <1.0.0" intl: ">=0.0.0 <1.0.0"
mime: ^0.9.3 mime: ^0.9.3

View file

@ -8,12 +8,14 @@ import 'package:test/test.dart';
main() { main() {
Angel app; Angel app;
AngelHttp http;
Directory testDir = const LocalFileSystem().directory('test'); Directory testDir = const LocalFileSystem().directory('test');
String url; String url;
Client client = new Client(); Client client = new Client();
setUp(() async { setUp(() async {
app = new Angel(); app = new Angel();
http = new AngelHttp(app);
app.logger = new Logger('angel')..onRecord.listen(print); app.logger = new Logger('angel')..onRecord.listen(print);
app.use( app.use(
@ -26,6 +28,7 @@ main() {
app.use( app.use(
new VirtualDirectory(app, const LocalFileSystem(), new VirtualDirectory(app, const LocalFileSystem(),
source: testDir, source: testDir,
useStream: false,
indexFileNames: ['index.php', 'index.txt']).handleRequest, indexFileNames: ['index.php', 'index.txt']).handleRequest,
); );
@ -33,12 +36,12 @@ main() {
app.dumpTree(showMatchers: true); app.dumpTree(showMatchers: true);
var server = await app.startServer(); var server = await http.startServer();
url = "http://${server.address.host}:${server.port}"; url = "http://${server.address.host}:${server.port}";
}); });
tearDown(() async { tearDown(() async {
if (app.httpServer != null) await app.httpServer.close(force: true); if (http.httpServer != null) await http.httpServer.close(force: true);
}); });
test('can serve files, with correct Content-Type', () async { test('can serve files, with correct Content-Type', () async {

View file

@ -5,8 +5,10 @@ import 'package:file/local.dart';
main() async { main() async {
Angel app; Angel app;
AngelHttp http;
Directory testDir = const LocalFileSystem().directory('test'); Directory testDir = const LocalFileSystem().directory('test');
app = new Angel(); app = new Angel();
http = new AngelHttp(app);
app.use( app.use(
new CachingVirtualDirectory(app, const LocalFileSystem(), new CachingVirtualDirectory(app, const LocalFileSystem(),
@ -20,6 +22,6 @@ main() async {
app.dumpTree(showMatchers: true); app.dumpTree(showMatchers: true);
var server = await app.startServer(); var server = await http.startServer();
print('Open at http://${server.address.host}:${server.port}'); print('Open at http://${server.address.host}:${server.port}');
} }

View file

@ -9,12 +9,14 @@ import 'package:test/test.dart';
main() { main() {
Angel app; Angel app;
AngelHttp http;
Directory testDir = const LocalFileSystem().directory('test'); Directory testDir = const LocalFileSystem().directory('test');
String url; String url;
Client client = new Client(); Client client = new Client();
setUp(() async { setUp(() async {
app = new Angel(); app = new Angel();
http = new AngelHttp(app);
app.use( app.use(
new CachingVirtualDirectory(app, const LocalFileSystem(), new CachingVirtualDirectory(app, const LocalFileSystem(),
@ -34,12 +36,12 @@ main() {
if (rec.stackTrace != null) print(rec.stackTrace); if (rec.stackTrace != null) print(rec.stackTrace);
}); });
var server = await app.startServer(); var server = await http.startServer();
url = "http://${server.address.host}:${server.port}"; url = "http://${server.address.host}:${server.port}";
}); });
tearDown(() async { tearDown(() async {
if (app.httpServer != null) await app.httpServer.close(force: true); if (http.httpServer != null) await http.httpServer.close(force: true);
}); });
test('sets etag, cache-control, expires, last-modified', () async { test('sets etag, cache-control, expires, last-modified', () async {