1.3.0-alpha

This commit is contained in:
Tobe O 2017-09-24 01:02:10 -04:00
parent 393c4bff02
commit 3f2c29571b
6 changed files with 71 additions and 54 deletions

View file

@ -9,25 +9,27 @@ In `pubspec.yaml`:
```yaml ```yaml
dependencies: dependencies:
angel_static: ^1.3.0 angel_static: ^1.3.0-alpha
``` ```
# Usage # Usage
To serve files from a directory, you need to create a `VirtualDirectory`. 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 ```dart
import 'dart:io';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';
import 'package:angel_static/angel_static.dart'; import 'package:angel_static/angel_static.dart';
import 'package:file/local.dart';
main() async { main() async {
var app = new Angel(); var app = new Angel();
var fs = const LocalFileSystem();
// Normal static server // 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 // 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 // Mount the VirtualDirectory's request handler
app.use(vDir.handleRequest); app.use(vDir.handleRequest);

View file

@ -128,38 +128,16 @@ class CachingVirtualDirectory extends VirtualDirectory {
} }
} }
var queue = new StreamQueue(file.openRead()); return file.readAsBytes().then((buf) {
return new Future<bool>(() async {
var buf = new Uint8List(50), hanging = <int>[];
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));
}
}
var etag = _etags[file.absolute.path] = weakEtag(buf); var etag = _etags[file.absolute.path] = weakEtag(buf);
res.statusCode = 200; res.statusCode = 200;
res.headers res.headers
..['ETag'] = etag ..['ETag'] = etag
..['content-type'] = ..['content-type'] =
lookupMimeType(file.path) ?? 'application/octet-stream'; lookupMimeType(file.path) ?? 'application/octet-stream';
setCachedHeaders(stat.modified, req, res); setCachedHeaders(stat.modified, req, res);
res.add(buf); res.add(buf);
res.add(hanging); return false;
return queue.rest.pipe(res).then((_) => false);
}); });
} }
} }

View file

@ -12,7 +12,7 @@ dependencies:
mime: ^0.9.3 mime: ^0.9.3
path: ^1.4.2 path: ^1.4.2
dev_dependencies: dev_dependencies:
angel_test: ^1.0.0 angel_test: ^1.1.0-alpha
http: ^0.11.3 http: ^0.11.3
mustache4dart: ^1.1.0 mustache4dart: ^1.1.0
test: ^0.12.13 test: ^0.12.13

View file

@ -75,28 +75,4 @@ main() {
}); });
expect(response.body, equals("index!")); 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');
});
} }

View file

@ -3,6 +3,7 @@ import 'package:angel_static/angel_static.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:http/http.dart' show Client; import 'package:http/http.dart' show Client;
import 'package:logging/logging.dart';
import 'package:matcher/matcher.dart'; import 'package:matcher/matcher.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
@ -26,6 +27,13 @@ main() {
app.dumpTree(showMatchers: true); 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(); var server = await app.startServer();
url = "http://${server.address.host}:${server.port}"; url = "http://${server.address.host}:${server.port}";
}); });
@ -43,7 +51,7 @@ main() {
expect(response.statusCode, equals(200)); expect(response.statusCode, equals(200));
expect( expect(
['ETag', 'cache-control', 'expires', 'last-modified'], ['etag', 'cache-control', 'expires', 'last-modified'],
everyElement(predicate( everyElement(predicate(
response.headers.containsKey, 'contained in response headers'))); response.headers.containsKey, 'contained in response headers')));
}); });

53
test/push_state_test.dart Normal file
View file

@ -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');
});
}