Dart 2 fixes + bump version + allow buffering
This commit is contained in:
parent
6945c538c3
commit
cceabd3c7d
9 changed files with 51 additions and 26 deletions
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
analyzer:
|
analyzer:
|
||||||
strong-mode: true
|
strong-mode:
|
||||||
|
implicit-casts: false
|
|
@ -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}');
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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}');
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue